Skip to content

Commit

Permalink
Added Register block for TinyALu
Browse files Browse the repository at this point in the history
- Added a RDL file for TinyALu register block
- Generated SV RTL reg block with apb interface and instantiated in
  TinyALU
- Add assigns for register fields from TinyALu

Signed-off-by: Raviteja Chatta <crteja@lowrisc.org>
  • Loading branch information
crteja authored and raysalemi committed Aug 9, 2023
1 parent 30ada79 commit ea8e281
Show file tree
Hide file tree
Showing 5 changed files with 460 additions and 6 deletions.
3 changes: 2 additions & 1 deletion examples/TinyALU/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ export COCOTB_REDUCED_LOG_FMT = 1
SIM ?= icarus
TOPLEVEL_LANG ?= verilog
ifeq ($(TOPLEVEL_LANG),verilog)
VERILOG_SOURCES =$(CWD)/hdl/verilog/tinyalu.sv
VERILOG_SOURCES =$(CWD)/hdl/verilog/TinyALUreg_pkg.sv $(CWD)/hdl/verilog/tinyalu.sv $(CWD)/hdl/verilog/TinyALUreg.sv

else ifeq ($(TOPLEVEL_LANG),vhdl)
VHDL_SOURCES=$(CWD)/hdl/vhdl/single_cycle_add_and_xor.vhd \
$(CWD)/hdl/vhdl/three_cycle_mult.vhd \
Expand Down
54 changes: 54 additions & 0 deletions examples/TinyALU/TinyALUreg.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
addrmap TinyALUreg {
name = "TinyALUreg";
desc = "Register description of TinyALU";
default regwidth = 16;

reg {
name = "source data reg";
field {
desc = "source data register 0";
hw=w; sw=r;
} data0[7:0] = 0;

field {
desc = "source data register 1";
hw=w; sw=r;
} data1[15:8] = 0;

} SRC @ 0x0;

reg {
name = "result data reg";

field {
desc = "result data";
hw=w; sw=r;
} data[15:0] = 0;

} RESULT @ 0x2;

reg {
name = "Command and status register";

field {
desc = "operation";
hw=rw; sw=rw;
} op[4:0] = 0;

field {
desc = "start";
hw=rw; sw=rw;
} start = 0;

field {
desc = "Done";
hw=rw; sw=rw;
} done = 0;

field {
desc = "reserved field";
hw=rw; sw=rw;
} reserved[14:8] = 0;

} CMD @ 0x4;
};
279 changes: 279 additions & 0 deletions examples/TinyALU/hdl/verilog/TinyALUreg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
// https://github.com/SystemRDL/PeakRDL-regblock

module TinyALUreg (
input wire clk,
input wire rst,

input wire s_apb_psel,
input wire s_apb_penable,
input wire s_apb_pwrite,
input wire [2:0] s_apb_paddr,
input wire [15:0] s_apb_pwdata,
output logic s_apb_pready,
output logic [15:0] s_apb_prdata,
output logic s_apb_pslverr,

input TinyALUreg_pkg::TinyALUreg__in_t hwif_in,
output TinyALUreg_pkg::TinyALUreg__out_t hwif_out
);

//--------------------------------------------------------------------------
// CPU Bus interface logic
//--------------------------------------------------------------------------
logic cpuif_req;
logic cpuif_req_is_wr;
logic [2:0] cpuif_addr;
logic [15:0] cpuif_wr_data;
logic [15:0] cpuif_wr_biten;
logic cpuif_req_stall_wr;
logic cpuif_req_stall_rd;

logic cpuif_rd_ack;
logic cpuif_rd_err;
logic [15:0] cpuif_rd_data;

logic cpuif_wr_ack;
logic cpuif_wr_err;

// Request
logic is_active;
always_ff @(posedge clk) begin
if(rst) begin
is_active <= '0;
cpuif_req <= '0;
cpuif_req_is_wr <= '0;
cpuif_addr <= '0;
cpuif_wr_data <= '0;
end else begin
if(~is_active) begin
if(s_apb_psel) begin
is_active <= '1;
cpuif_req <= '1;
cpuif_req_is_wr <= s_apb_pwrite;
cpuif_addr <= {s_apb_paddr[2:1], 1'b0};
cpuif_wr_data <= s_apb_pwdata;
end
end else begin
cpuif_req <= '0;
if(cpuif_rd_ack || cpuif_wr_ack) begin
is_active <= '0;
end
end
end
end
assign cpuif_wr_biten = '1;

// Response
assign s_apb_pready = cpuif_rd_ack | cpuif_wr_ack;
assign s_apb_prdata = cpuif_rd_data;
assign s_apb_pslverr = cpuif_rd_err | cpuif_wr_err;

logic cpuif_req_masked;

// Read & write latencies are balanced. Stalls not required
assign cpuif_req_stall_rd = '0;
assign cpuif_req_stall_wr = '0;
assign cpuif_req_masked = cpuif_req
& !(!cpuif_req_is_wr & cpuif_req_stall_rd)
& !(cpuif_req_is_wr & cpuif_req_stall_wr);

//--------------------------------------------------------------------------
// Address Decode
//--------------------------------------------------------------------------
typedef struct {
logic SRC;
logic RESULT;
logic CMD;
} decoded_reg_strb_t;
decoded_reg_strb_t decoded_reg_strb;
logic decoded_req;
logic decoded_req_is_wr;
logic [15:0] decoded_wr_data;
logic [15:0] decoded_wr_biten;

always_comb begin
decoded_reg_strb.SRC = cpuif_req_masked & (cpuif_addr == 3'h0);
decoded_reg_strb.RESULT = cpuif_req_masked & (cpuif_addr == 3'h2);
decoded_reg_strb.CMD = cpuif_req_masked & (cpuif_addr == 3'h4);
end

// Pass down signals to next stage
assign decoded_req = cpuif_req_masked;
assign decoded_req_is_wr = cpuif_req_is_wr;
assign decoded_wr_data = cpuif_wr_data;
assign decoded_wr_biten = cpuif_wr_biten;

//--------------------------------------------------------------------------
// Field logic
//--------------------------------------------------------------------------
typedef struct {
struct {
struct {
logic [4:0] next;
logic load_next;
} op;
struct {
logic next;
logic load_next;
} start;
struct {
logic next;
logic load_next;
} done;
struct {
logic [6:0] next;
logic load_next;
} reserved;
} CMD;
} field_combo_t;
field_combo_t field_combo;

typedef struct {
struct {
struct {
logic [4:0] value;
} op;
struct {
logic value;
} start;
struct {
logic value;
} done;
struct {
logic [6:0] value;
} reserved;
} CMD;
} field_storage_t;
field_storage_t field_storage;

// Field: TinyALUreg.CMD.op
always_comb begin
automatic logic [4:0] next_c = field_storage.CMD.op.value;
automatic logic load_next_c = '0;
if(decoded_reg_strb.CMD && decoded_req_is_wr) begin // SW write
next_c = (field_storage.CMD.op.value & ~decoded_wr_biten[4:0]) | (decoded_wr_data[4:0] & decoded_wr_biten[4:0]);
load_next_c = '1;
end else begin // HW Write
next_c = hwif_in.CMD.op.next;
load_next_c = '1;
end
field_combo.CMD.op.next = next_c;
field_combo.CMD.op.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.CMD.op.value <= 5'h0;
end else if(field_combo.CMD.op.load_next) begin
field_storage.CMD.op.value <= field_combo.CMD.op.next;
end
end
assign hwif_out.CMD.op.value = field_storage.CMD.op.value;
// Field: TinyALUreg.CMD.start
always_comb begin
automatic logic [0:0] next_c = field_storage.CMD.start.value;
automatic logic load_next_c = '0;
if(decoded_reg_strb.CMD && decoded_req_is_wr) begin // SW write
next_c = (field_storage.CMD.start.value & ~decoded_wr_biten[5:5]) | (decoded_wr_data[5:5] & decoded_wr_biten[5:5]);
load_next_c = '1;
end else begin // HW Write
next_c = hwif_in.CMD.start.next;
load_next_c = '1;
end
field_combo.CMD.start.next = next_c;
field_combo.CMD.start.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.CMD.start.value <= 1'h0;
end else if(field_combo.CMD.start.load_next) begin
field_storage.CMD.start.value <= field_combo.CMD.start.next;
end
end
assign hwif_out.CMD.start.value = field_storage.CMD.start.value;
// Field: TinyALUreg.CMD.done
always_comb begin
automatic logic [0:0] next_c = field_storage.CMD.done.value;
automatic logic load_next_c = '0;
if(decoded_reg_strb.CMD && decoded_req_is_wr) begin // SW write
next_c = (field_storage.CMD.done.value & ~decoded_wr_biten[6:6]) | (decoded_wr_data[6:6] & decoded_wr_biten[6:6]);
load_next_c = '1;
end else begin // HW Write
next_c = hwif_in.CMD.done.next;
load_next_c = '1;
end
field_combo.CMD.done.next = next_c;
field_combo.CMD.done.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.CMD.done.value <= 1'h0;
end else if(field_combo.CMD.done.load_next) begin
field_storage.CMD.done.value <= field_combo.CMD.done.next;
end
end
assign hwif_out.CMD.done.value = field_storage.CMD.done.value;
// Field: TinyALUreg.CMD.reserved
always_comb begin
automatic logic [6:0] next_c = field_storage.CMD.reserved.value;
automatic logic load_next_c = '0;
if(decoded_reg_strb.CMD && decoded_req_is_wr) begin // SW write
next_c = (field_storage.CMD.reserved.value & ~decoded_wr_biten[14:8]) | (decoded_wr_data[14:8] & decoded_wr_biten[14:8]);
load_next_c = '1;
end else begin // HW Write
next_c = hwif_in.CMD.reserved.next;
load_next_c = '1;
end
field_combo.CMD.reserved.next = next_c;
field_combo.CMD.reserved.load_next = load_next_c;
end
always_ff @(posedge clk) begin
if(rst) begin
field_storage.CMD.reserved.value <= 7'h0;
end else if(field_combo.CMD.reserved.load_next) begin
field_storage.CMD.reserved.value <= field_combo.CMD.reserved.next;
end
end
assign hwif_out.CMD.reserved.value = field_storage.CMD.reserved.value;

//--------------------------------------------------------------------------
// Write response
//--------------------------------------------------------------------------
assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
// Writes are always granted with no error response
assign cpuif_wr_err = '0;

//--------------------------------------------------------------------------
// Readback
//--------------------------------------------------------------------------

logic readback_err;
logic readback_done;
logic [15:0] readback_data;

// Assign readback values to a flattened array
logic [15:0] readback_array[3];
assign readback_array[0][7:0] = (decoded_reg_strb.SRC && !decoded_req_is_wr) ? hwif_in.SRC.data0.next : '0;
assign readback_array[0][15:8] = (decoded_reg_strb.SRC && !decoded_req_is_wr) ? hwif_in.SRC.data1.next : '0;
assign readback_array[1][15:0] = (decoded_reg_strb.RESULT && !decoded_req_is_wr) ? hwif_in.RESULT.data.next : '0;
assign readback_array[2][4:0] = (decoded_reg_strb.CMD && !decoded_req_is_wr) ? field_storage.CMD.op.value : '0;
assign readback_array[2][5:5] = (decoded_reg_strb.CMD && !decoded_req_is_wr) ? field_storage.CMD.start.value : '0;
assign readback_array[2][6:6] = (decoded_reg_strb.CMD && !decoded_req_is_wr) ? field_storage.CMD.done.value : '0;
assign readback_array[2][7:7] = '0;
assign readback_array[2][14:8] = (decoded_reg_strb.CMD && !decoded_req_is_wr) ? field_storage.CMD.reserved.value : '0;
assign readback_array[2][15:15] = '0;

// Reduce the array
always_comb begin
automatic logic [15:0] readback_data_var;
readback_done = decoded_req & ~decoded_req_is_wr;
readback_err = '0;
readback_data_var = '0;
for(int i=0; i<3; i++) readback_data_var |= readback_array[i];
readback_data = readback_data_var;
end

assign cpuif_rd_ack = readback_done;
assign cpuif_rd_data = readback_data;
assign cpuif_rd_err = readback_err;
endmodule

0 comments on commit ea8e281

Please sign in to comment.