diff --git a/cadence/heron_comma_fix/functional/verilog.v b/cadence/heron_comma_fix/functional/verilog.v new file mode 100644 index 0000000..35a132d --- /dev/null +++ b/cadence/heron_comma_fix/functional/verilog.v @@ -0,0 +1,12 @@ +module heron_comma_fix (A,Y); + parameter comma = 8; + parameter comma_fix = comma / 2; + + + input [31:0] A; + output [31:0] Y; + wire [31:0] Y; + + assign Y[(31 - comma_fix):0] = A[(31 - comma_fix):0]; + assign Y[31:(31 - comma_fix)] = 0; +endmodule diff --git a/cadence/heron_ctrl/functional/verilog.v b/cadence/heron_ctrl/functional/verilog.v new file mode 100644 index 0000000..6e8a889 --- /dev/null +++ b/cadence/heron_ctrl/functional/verilog.v @@ -0,0 +1,113 @@ +`include "heron_states.v" + +module heron_ctrl( + ctrl_bus, + // rest + state, + ready, + ram_rd_en, + ram_wr_en); + + // readability + parameter ON = 1'b1; + parameter OFF = 1'b0; + parameter MINUS = 1'b1; + + input [3:0] state; + output ready; + output ram_rd_en, ram_wr_en; + + output [22:0] ctrl_bus; + `define CTRL_WIRE(name,port) \ + reg name; \ + assign ctrl_bus[port] = name; + `include "heron_ctrl_wires.v" + `undef CTRL_WIRE + + reg ready = OFF; + reg ram_rd_en = OFF; + reg ram_wr_en = OFF; + + always @(state) begin + ready = OFF; + ram_rd_en = OFF; + ram_wr_en = OFF; + + `define CTRL_WIRE(name,port) name = OFF; + `include "heron_ctrl_wires.v" + `undef CTRL_WIRE + + case (state) + `IDLE: begin + ready = ON; + end + `LD_N_1: begin + k0_to_a = ON; + a_to_eab = ON; + edb_to_din = ON; + ram_rd_en = ON; + end + `LD_N_2: begin + din_to_a = ON; + k0_to_b = ON; + alu_set_z = ON; + end + `I_GT_ZERO: begin + alu_res_to_a = ON; + a_to_i = ON; + end + `LD_S_1: begin + i_to_a = ON; + edb_to_din = ON; + a_to_eab = ON; + ram_rd_en = ON; + end + `LD_S_2: begin + din_to_a = ON; + a_to_s = ON; + k1_to_b = ON; + alu_mode = MINUS; + alu_set_s = ON; + alu_set_z = ON; + end + `S_GT_ONE:; // noop + `X_1: begin + s_to_a_shift_1 = ON; + s_to_b = ON; + + a_to_old_x = ON; + a_to_x = ON; + end + `DIV_1: begin + x_to_a = ON; + s_to_b = ON; + end + `DIV_2:; // noop + `DIV_3:; // noop + `DIV_4: begin + x_to_a = ON; + div_to_b_shift_1 = ON; + end + `OLD_X_LTE_X_1: begin + alu_res_to_a = ON; + a_to_x = ON; + old_x_to_b = ON; + alu_set_c = ON; + end + `OLD_X_LTE_X_2: begin + x_to_a = ON; + a_to_old_x = ON; + end + `STORE_X: begin + x_to_b_shifted = ON; + ram_wr_en = ON; + end + `DEC_I: begin + i_to_a = ON; + k1_to_b = ON; + alu_mode = MINUS; + alu_set_z = ON; + end + endcase + end +endmodule diff --git a/cadence/heron_ctrl_tb/functional/verilog.v b/cadence/heron_ctrl_tb/functional/verilog.v new file mode 100644 index 0000000..bb91cf0 --- /dev/null +++ b/cadence/heron_ctrl_tb/functional/verilog.v @@ -0,0 +1,25 @@ +module heron_fsm_tb; + task assert; + input condition; + input [(20*8 - 1):0] message; + begin + if (condition !== 1'b1) + begin + $display("Assertion Failed: %s", message); + $finish(2); + end + end + endtask + + reg[3:0] state; + + initial begin + $dumpfile("ctrl.vcd"); + $dumpvars; + end + + initial begin + $display("Control logic tests passed!"); + $finish; + end +end diff --git a/cadence/heron_ctrl_wires/functional/verilog.v b/cadence/heron_ctrl_wires/functional/verilog.v new file mode 100644 index 0000000..97beaa3 --- /dev/null +++ b/cadence/heron_ctrl_wires/functional/verilog.v @@ -0,0 +1,33 @@ +module heron_ctrl_wires ( + ctrl_bus, + a_to_eab, + a_to_i, + a_to_old_x, + a_to_s, + a_to_x, + alu_mode, + alu_res_to_a, + alu_set_c, + alu_set_s, + alu_set_z, + din_to_a, + div_to_b_shift_1, + edb_to_din, + i_to_a, + k0_to_a, + k0_to_b, + k1_to_b, + old_x_to_b, + s_to_a_shift_1, + s_to_b, + x_to_a, + x_to_b_shifted +); + + input [22:0] ctrl_bus; + `define CTRL_WIRE(name,port) \ + output name; \ + assign name = ctrl_bus[port]; + `include "heron_ctrl_wires.v" + `undef CTRL_WIRE +endmodule diff --git a/cadence/heron_fsm/functional/verilog.v b/cadence/heron_fsm/functional/verilog.v new file mode 100644 index 0000000..1e92e0a --- /dev/null +++ b/cadence/heron_fsm/functional/verilog.v @@ -0,0 +1,68 @@ +`include "heron_states.v" + +module heron_fsm(clk, load, reset, flag_z, flag_c, flag_s, state); + input clk; + input load; + input reset; + + input flag_z; + input flag_c; + input flag_s; + + output [3:0] state; + + reg [3:0] state = `IDLE; + reg [3:0] next_state = `IDLE; + + always @(posedge clk or posedge reset) + if(reset) begin + state <= `IDLE; + end else begin + state <= next_state; + end + + always @(state or flag_z or load) + case(state) + `IDLE: begin + if(load) begin + next_state = `LD_N_1; + end else begin + next_state = `IDLE; + end + end + `LD_N_1: next_state = `LD_N_2; + `LD_N_2: next_state = `I_GT_ZERO; + `I_GT_ZERO: begin + if (flag_z) begin + next_state = `IDLE; + end else begin + next_state = `LD_S_1; + end + end + `LD_S_1: next_state = `LD_S_2; + `LD_S_2: next_state = `S_GT_ONE; + `S_GT_ONE: begin + if (flag_s || flag_z) begin + next_state = `STORE_X; + end else begin + next_state = `X_1; + end + end + `X_1: next_state = `DIV_2; + `DIV_1: next_state = `DIV_2; + `DIV_2: next_state = `DIV_3; + `DIV_3: next_state = `DIV_4; + `DIV_4: next_state = `OLD_X_LTE_X_1; + `OLD_X_LTE_X_1: next_state = `OLD_X_LTE_X_2; + `OLD_X_LTE_X_2: begin + if (flag_c) begin + next_state = `DIV_1; + end else begin + next_state = `STORE_X; + end + end + `STORE_X: next_state = `DEC_I; + `DEC_I: next_state = `I_GT_ZERO; + endcase +endmodule + diff --git a/cadence/heron_fsm_tb/functional/verilog.v b/cadence/heron_fsm_tb/functional/verilog.v new file mode 100644 index 0000000..69326ef --- /dev/null +++ b/cadence/heron_fsm_tb/functional/verilog.v @@ -0,0 +1,66 @@ +`include "heron_states.v" + +module heron_fsm_tb; + task assert; + input condition; + input [(20*8 - 1):0] message; + begin + if (condition !== 1'b1) + begin + $display("Assertion Failed: %s", message); + $finish(2); + end + end + endtask + + parameter CYCLE = 50; + + reg clk, reset; + reg load; + reg flag_z, flag_c, flag_s; + + wire[3:0] state; + + heron_fsm fsm( + .clk(clk), + .reset(reset), + .load(load), + .state(state), + .flag_z(flag_z), + .flag_c(flag_c), + .flag_s(flag_s) + ); + + initial clk = 1'b0; + always #(CYCLE/2) clk = ~clk; + + initial begin + $dumpfile("fsm.vcd"); + $dumpvars; + end + + initial begin + reset = 1'b1; + #(3*CYCLE) + reset = 1'b0; + end + + initial begin + load = 0; + #(5*CYCLE) + load = 1; + #(CYCLE) + load = 0; + + assert(state == `LD_N_1, "IDLE -> LD_N_1"); + #(CYCLE) + assert(state == `LD_N_2, "LD_N_1 -> LD_N_2"); + #(CYCLE) + assert(state == `I_GT_ZERO, "LD_N_2 -> I_GT_ZERO"); + #(CYCLE) + assert(state == `I_GT_ZERO, "LD_N_2 -> I_GT_ZERO"); + + $display("FSM tests passed!"); + $finish; + end +endmodule diff --git a/cadence/heron_scaler64_to_32/functional/verilog.v b/cadence/heron_scaler64_to_32/functional/verilog.v new file mode 100644 index 0000000..c4b1882 --- /dev/null +++ b/cadence/heron_scaler64_to_32/functional/verilog.v @@ -0,0 +1,7 @@ +module heron_scaler64_to_32 (A,Y); + input [63:0] A; + output [31:0] Y; + wire [31:0] Y; + assign Y[30:0] = A[63:33]; + assign Y[31] = 0; +endmodule diff --git a/cadence/heron_shift_1/functional/verilog.v b/cadence/heron_shift_1/functional/verilog.v new file mode 100644 index 0000000..f35454d --- /dev/null +++ b/cadence/heron_shift_1/functional/verilog.v @@ -0,0 +1,10 @@ +module heron_shift_1 (A, Y); + + input [31:0] A; + output [31:0] Y; + + wire [31:0] Y; + assign Y[30:0] = A[31:1]; + assign Y[31] = 0; + +endmodule diff --git a/cadence/heron_top_tb/functional/verilog.v b/cadence/heron_top_tb/functional/verilog.v new file mode 100644 index 0000000..87d6dcc --- /dev/null +++ b/cadence/heron_top_tb/functional/verilog.v @@ -0,0 +1,125 @@ +`include "heron_states.v" + +module heron_top_tb(); +`define ASSERT(c, msg) if (!c) begin $display("%c[31mAssertion Failed: %s%c[0m", 27, msg, 27); $finish(2); end +`define ASSERT_STATE(state) `ASSERT((fsm_state == state), "not expected state") + +parameter CYCLE = 50; + +wire [31:0] edb; +wire [31:0] eab; +wire ready; +wire ram_wr_en, ram_rd_en; +wire [3:0] fsm_state; +assign fsm_state = heron.fsm.state; + +reg reset; +reg load = 0; +reg [15:0] i; + +reg clk = 1'b0; +always #(CYCLE/2) clk = ~clk; + +reg [31:0] ram [0:1023]; + +wire ram0; +wire ram1; +wire ram2; +assign ram0 = ram[0]; +assign ram1 = ram[1]; +assign ram2 = ram[2]; + +assign edb = ram_rd_en ? ram[eab[9:0]] : 32'bz; + +always @ (posedge clk) begin + if (ram_wr_en) begin + ram[eab[9:0]] <= edb; + end +end + +heron_top heron( + .clk(clk), + .load(load), + .reset(reset), + .edb(edb), + .eab(eab), + .ram_rd_en(ram_rd_en), + .ram_wr_en(ram_wr_en), + .ready(ready) +); + +initial begin + $dumpfile("heron_top_tb.vcd"); + $dumpvars; + + ram[0] = 3; + ram[3] = 4; + + ram[2] = 0; + ram[1] = 1; +end + +initial begin + `ASSERT_STATE(`IDLE) + #(5*CYCLE) + load = 1; + #(CYCLE) + load = 0; + // load mem[0] -> number of operands + `ASSERT_STATE(`LD_N_1) + #(CYCLE) + // load... + `ASSERT_STATE(`LD_N_2) + #(CYCLE) + // if (mem[0] > 0) then + `ASSERT_STATE(`I_GT_ZERO) + #(CYCLE) + // load mem[1]... + `ASSERT_STATE(`LD_S_1) + #(CYCLE) + // ...load + `ASSERT_STATE(`LD_S_2) + #(CYCLE) + // if (mem[1] > 1) then + `ASSERT_STATE(`S_GT_ONE) + #(CYCLE) + // x_0 = s / 2 + `ASSERT_STATE(`X_1) + #(CYCLE) + // s / x_n... + `ASSERT_STATE(`DIV_2) + #(CYCLE) + // ..divide + `ASSERT_STATE(`DIV_3) + #(CYCLE) + // x_1 = x_n + (s / x_n) / 2 + `ASSERT_STATE(`DIV_4) + #(CYCLE) + // if (old_x <= x_1) ... + `ASSERT_STATE(`OLD_X_LTE_X_1) + #(CYCLE) + // ... then + `ASSERT_STATE(`OLD_X_LTE_X_2) + #(CYCLE) + // store mem[1] = 2 + `ASSERT_STATE(`STORE_X) + #(CYCLE) + // i-- + `ASSERT(ram[3] == 2, "sqrt(4) == 2") + `ASSERT(ram[3] == 1, "sqrt(4) == 2") + `ASSERT_STATE(`DEC_I) + #(CYCLE) + // if (i > 0) then ... + `ASSERT_STATE(`I_GT_ZERO) + + for (i = 0; i < 1000; i = i + 1) begin + if (ready != 0) begin + $display("%c[32mSUCCESS: heron_top_tb tests bench finished;%c[0m", 27, 27); + $finish; + end + #(CYCLE) ; + end + $display("%c[31mFAILED: heron_top_tb tests timeout!%c[0m", 27, 27); + $finish(1); +end +endmodule