diff --git a/rtl/ser_eq.v b/rtl/ser_eq.v new file mode 100644 index 0000000..f143973 --- /dev/null +++ b/rtl/ser_eq.v @@ -0,0 +1,15 @@ +module ser_eq + ( + input clk, + input a, + input b, + input clr, + output q); + + reg eq = 1'b1; + + assign q = eq & (a == b); + always @(posedge clk) + eq <= q | clr; + +endmodule diff --git a/rtl/serv_alu.v b/rtl/serv_alu.v index c1bb7e1..18dabfe 100644 --- a/rtl/serv_alu.v +++ b/rtl/serv_alu.v @@ -6,6 +6,8 @@ module serv_alu input [2:0] i_funct3, input i_rs1, input i_op_b, + input i_cmp_en, + output o_cmp, output o_rd); localparam [2:0] @@ -16,7 +18,11 @@ module serv_alu ORI = 3'b110, ANDI = 3'b111; + localparam[2:0] + BEQ = 3'b000; + wire result_add; + wire result_eq; ser_add ser_add ( @@ -26,7 +32,19 @@ module serv_alu .clr (!i_en), .q (result_add)); + reg eq; + + ser_eq ser_eq + ( + .clk (clk), + .a (i_rs1), + .b (i_op_b), + .clr (!i_cmp_en), + .q (result_eq)); + + assign o_cmp = (i_funct3 == BEQ) ? result_eq : 1'bx; + assign o_rd = (i_funct3 == ADDI) ? result_add : 1'b0; -endmodule +endmodule diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 9e4facb..c212e0d 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -6,16 +6,19 @@ module serv_decode output reg o_i_rd_rdy = 1'b1, output o_ctrl_en, output o_ctrl_jump, - output [2:0] o_funct3, output o_rf_rd_en, output [4:0] o_rf_rd_addr, output o_rf_rs_en, output [4:0] o_rf_rs1_addr, output [4:0] o_rf_rs2_addr, + output o_alu_cmp_en, + input i_alu_cmp, output o_mem_en, + output o_mem_cmd, output o_mem_init, output o_mem_dat_valid, input i_mem_busy, + output [2:0] o_funct3, output reg o_imm, output o_offset_source, output o_op_b_source, @@ -24,35 +27,43 @@ module serv_decode `include "serv_params.vh" - localparam [1:0] - IDLE = 2'd0, - MEM_INIT = 2'd1, - MEM_WAIT = 2'd2, - RUN = 2'd3; + localparam [2:0] + IDLE = 3'd0, + COMPARE = 3'd1, + MEM_INIT = 3'd2, + MEM_WAIT = 3'd3, + RUN = 3'd4; localparam [4:0] - OP_LOAD = 5'b00000, - OP_OPIMM = 5'b00100, - OP_LUI = 5'b01101, - OP_JAL = 5'b11011; + OP_LOAD = 5'b00000, + OP_STORE = 5'b01000, + OP_OPIMM = 5'b00100, + OP_LUI = 5'b01101, + OP_BRANCH = 5'b11000, + OP_JAL = 5'b11011; + + reg [2:0] state = 3'd0; - reg [1:0] state = 2'd0; - reg [4:0] cnt = 5'd0; wire running; wire mem_op; - assign mem_op = (opcode == OP_LOAD); + assign mem_op = (opcode == OP_LOAD) | (opcode == OP_STORE); assign o_ctrl_en = running; - assign o_ctrl_jump = (opcode == OP_JAL); + assign o_ctrl_jump = (opcode == OP_JAL) | + ((opcode == OP_BRANCH) & i_alu_cmp); assign o_rf_rd_en = running & ((opcode == OP_JAL) | (opcode == OP_OPIMM) | (opcode == OP_LUI)); assign o_rf_rs_en = (running & (opcode == OP_OPIMM)) | (state == MEM_INIT); + assign o_alu_cmp_en = (state == COMPARE); + assign o_mem_en = mem_op & cnt_en; + assign o_mem_cmd = (opcode == OP_STORE); + assign o_mem_init = (state == MEM_INIT); assign o_rf_rd_addr = i_i_rd_dat[11:7]; @@ -61,7 +72,8 @@ module serv_decode assign o_rf_rs2_addr = i_i_rd_dat[24:20]; assign o_offset_source = (opcode == OP_JAL) ? OFFSET_SOURCE_IMM : 1'b0; - assign o_op_b_source = (opcode == OP_OPIMM) ? OP_B_SOURCE_IMM : 1'b0; + assign o_op_b_source = (opcode == OP_OPIMM) ? OP_B_SOURCE_IMM : + (opcode == OP_BRANCH) ? OP_B_SOURCE_RS2 : 1'bx; assign o_mem_dat_valid = (o_funct3[1:0] == 2'b00) ? cnt < 8 : (o_funct3[1:0] == 2'b01) ? cnt < 16 : 1'b1; @@ -90,11 +102,24 @@ module serv_decode else if (opcode == OP_LOAD) if (cnt > 10) o_imm = i_i_rd_dat[31]; else o_imm = i_i_rd_dat[cnt+20]; + else if (opcode == OP_BRANCH) + if (cnt > 11) o_imm = i_i_rd_dat[31]; + else if (cnt > 10) o_imm = i_i_rd_dat[7]; + else if (cnt > 4) o_imm = i_i_rd_dat[cnt+20]; + else if (cnt > 0) o_imm = i_i_rd_dat[cnt+7]; + else o_imm = 1'b0; + else if (opcode == OP_STORE) + if (cnt > 10) o_imm = i_i_rd_dat[31]; + else if (cnt > 4) o_imm = i_i_rd_dat[cnt+20]; + else o_imm = i_i_rd_dat[cnt+7]; end wire go = i_i_rd_vld & o_i_rd_rdy; - wire cnt_en = (state == RUN) | (state == MEM_INIT); + wire cnt_en = + (state == RUN) | + (state == COMPARE) | + (state == MEM_INIT); wire cnt_done = cnt == 31; assign running = (state == RUN); @@ -104,7 +129,12 @@ module serv_decode case (state) IDLE : begin if (go) - state <= mem_op ? MEM_INIT : RUN; + state <= (opcode == OP_BRANCH) ? COMPARE : + mem_op ? MEM_INIT : RUN; + end + COMPARE : begin + if (cnt_done) + state <= RUN; end MEM_INIT : if (cnt_done) diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index 61a5b2f..a86d522 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -19,12 +19,16 @@ module serv_mem_if input i_d_ca_rdy, output [31:0] o_d_dm_dat, output [3:0] o_d_dm_msk, - output o_d_dm_vld, + output reg o_d_dm_vld = 1'b0, input i_d_dm_rdy, input [31:0] i_d_rd_dat, input i_d_rd_vld, output o_d_rd_rdy); + wire ca_en = o_d_ca_vld & i_d_ca_rdy; + wire dm_en = o_d_dm_vld & i_d_dm_rdy; + wire rd_en = i_d_rd_vld & o_d_rd_rdy; + reg en_r; wire adr; reg [31:0] dat = 32'd0; @@ -54,17 +58,26 @@ module serv_mem_if assign o_d_rd_rdy = !i_en; //Likely bug, but probably doesn't matter - wire is_half = i_funct3[1]; + wire is_word = i_funct3[1]; + wire is_half = i_funct3[0]; wire is_byte = !(|i_funct3[1:0]); wire [1:0] bytepos = o_d_ca_adr[3:2]; wire upper_half = bytepos[1]; - + + assign o_d_dm_dat = dat; + assign o_d_dm_msk = is_word ? 4'b1111 : + is_half ? {{2{upper_half}}, ~{2{upper_half}}} : + 1'b1 << bytepos; + always @(posedge i_clk) begin signbit <= dat[0]; if (i_en & i_init) o_busy <= 1'b1; - else if (i_d_rd_vld & o_d_rd_rdy) begin + else if (rd_en | dm_en) + o_busy <= 1'b0; + + if (rd_en) begin dat[31:16] <= i_d_rd_dat[31:16]; dat[15:8] <= (is_half & upper_half) ? i_d_rd_dat[31:24] : i_d_rd_dat[15:8]; dat[7:0] <= (is_byte & (bytepos == 2'b11)) ? i_d_rd_dat[31:24] : @@ -72,15 +85,20 @@ module serv_mem_if (is_half & upper_half) ? i_d_rd_dat[23:16] : (is_byte & (bytepos == 2'b01)) ? i_d_rd_dat[15:8] : i_d_rd_dat[7:0]; - o_busy <= 1'b0; end en_r <= i_en; - if (o_d_ca_vld & i_d_ca_rdy) + if (ca_en) o_d_ca_vld <= 1'b0; - else if (en_r & !i_en) - o_d_ca_vld <= 1'b1; + else if (en_r & !i_en) begin + o_d_ca_vld <= 1'b1; + end + if (dm_en) + o_d_dm_vld <= 1'b0; + else if (en_r & !i_en) + o_d_dm_vld <= i_cmd; + if (i_en) dat <= {i_rs2,dat[31:1]}; end diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 4cfdadd..ac29e87 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -1,24 +1,54 @@ `default_nettype none + +`define RISCV_FORMAL +`define RISCV_FORMAL_NRET 1 +`define RISCV_FORMAL_XLEN 32 +`define RISCV_FORMAL_ILEN 32 +//`define RISCV_FORMAL_COMPRESSED +`define RISCV_FORMAL_ALIGNED_MEM + module serv_top ( - input clk, - output [31:0] o_i_ca_adr, - output o_i_ca_vld, - input i_i_ca_rdy, - input [31:0] i_i_rd_dat, - input i_i_rd_vld, - output o_i_rd_rdy, - output o_d_ca_cmd, - output [31:0] o_d_ca_adr, - output o_d_ca_vld, - input i_d_ca_rdy, - output [31:0] o_d_dm_dat, - output [3:0] o_d_dm_msk, - output o_d_dm_vld, - input i_d_dm_rdy, - input [31:0] i_d_rd_dat, - input i_d_rd_vld, - output o_d_rd_rdy); + input clk, +`ifdef RISCV_FORMAL + output reg rvfi_valid = 1'b0, + output reg [63:0] rvfi_order = 64'd0, + output reg [31:0] rvfi_insn = 32'd0, + output reg rvfi_trap = 1'b0, + output reg rvfi_halt = 1'b0, + output reg rvfi_intr = 1'b0, + output reg [1:0] rvfi_mode = 2'b11, + output reg [4:0] rvfi_rs1_addr, + output reg [4:0] rvfi_rs2_addr, + output reg [31:0] rvfi_rs1_rdata, + output reg [31:0] rvfi_rs2_rdata, + output reg [4:0] rvfi_rd_addr, + output reg [31:0] rvfi_rd_wdata, + output reg [31:0] rvfi_pc_rdata, + output reg [31:0] rvfi_pc_wdata, + output reg [31:0] rvfi_mem_addr, + output reg [3:0] rvfi_mem_rmask, + output reg [3:0] rvfi_mem_wmask, + output reg [31:0] rvfi_mem_rdata, + output reg [31:0] rvfi_mem_wdata, +`endif + output [31:0] o_i_ca_adr, + output o_i_ca_vld, + input i_i_ca_rdy, + input [31:0] i_i_rd_dat, + input i_i_rd_vld, + output o_i_rd_rdy, + output o_d_ca_cmd, + output [31:0] o_d_ca_adr, + output o_d_ca_vld, + input i_d_ca_rdy, + output [31:0] o_d_dm_dat, + output [3:0] o_d_dm_msk, + output o_d_dm_vld, + input i_d_dm_rdy, + input [31:0] i_d_rd_dat, + input i_d_rd_vld, + output o_d_rd_rdy); `include "serv_params.vh" @@ -39,6 +69,9 @@ module serv_top wire imm; wire [2:0] funct3; + + wire alu_cmp_en; + wire alu_cmp; wire rs1; wire rs2; @@ -50,7 +83,7 @@ module serv_top wire mem_en; - wire mem_cmd = 1'b0 /*FIXME*/; + wire mem_cmd; wire mem_dat_valid; wire mem_init; @@ -67,12 +100,15 @@ module serv_top .o_ctrl_en (ctrl_en), .o_ctrl_jump (jump), .o_funct3 (funct3), + .o_alu_cmp_en (alu_cmp_en), + .i_alu_cmp (alu_cmp), .o_rf_rd_en (rd_en), .o_rf_rd_addr (rd_addr), .o_rf_rs_en (rs_en), .o_rf_rs1_addr (rs1_addr), .o_rf_rs2_addr (rs2_addr), .o_mem_en (mem_en), + .o_mem_cmd (mem_cmd), .o_mem_init (mem_init), .o_mem_dat_valid (mem_dat_valid), .i_mem_busy (mem_busy), @@ -108,8 +144,10 @@ module serv_top serv_alu alu ( .clk (clk), - .i_en (ctrl_en), /*FIXME: Is this true?*/ + .i_en (ctrl_en), .i_funct3 (funct3), + .i_cmp_en (alu_cmp_en), + .o_cmp (alu_cmp), .i_rs1 (rs1), .i_op_b (op_b), .o_rd (alu_rd)); @@ -139,7 +177,7 @@ module serv_top .i_imm (imm), .o_rd (mem_rd), .o_busy (mem_busy), - //External interface + //External interface .o_d_ca_cmd (o_d_ca_cmd), .o_d_ca_adr (o_d_ca_adr), .o_d_ca_vld (o_d_ca_vld), @@ -152,4 +190,45 @@ module serv_top .i_d_rd_vld (i_d_rd_vld), .o_d_rd_rdy (o_d_rd_rdy)); +`ifdef RISCV_FORMAL + reg [31:0] rs1_fv, rs2_fv, rd_fv; + reg [31:0] pc = RESET_PC; + reg ctrl_en_r = 1'b0; + + always @(posedge clk) begin + ctrl_en_r <= ctrl_en; + if (rs_en) begin + rs1_fv <= {rs1,rs1_fv[31:1]}; + rs2_fv <= {rs2,rs2_fv[31:1]}; + end + if (rd_en) begin + rd_fv <= {rd,rd_fv[31:1]}; + end + rvfi_valid <= 1'b0; + if (ctrl_en_r & !ctrl_en) begin + pc <= o_i_ca_adr; + rvfi_valid <= 1'b1; + rvfi_order <= rvfi_order + 1; + rvfi_insn <= i_i_rd_dat; + rvfi_trap <= 1'b0; + rvfi_halt <= 1'b0; + rvfi_intr <= 1'b0; + rvfi_mode <= 2'd3; + rvfi_rs1_addr <= rs1_addr; + rvfi_rs2_addr <= rs2_addr; + rvfi_rs1_rdata <= rs1_fv; + rvfi_rs2_rdata <= rs2_fv; + rvfi_rd_addr <= rd_addr; + rvfi_rd_wdata <= rd_fv; + rvfi_pc_rdata <= pc; + rvfi_pc_wdata <= o_i_ca_adr; + rvfi_mem_addr <= o_d_ca_adr; + rvfi_mem_rmask <= 4'bxxxx; + rvfi_mem_wmask <= o_d_dm_msk; + rvfi_mem_rdata <= i_d_rd_dat; + rvfi_mem_wdata <= o_d_dm_dat; + end + end +`endif + endmodule diff --git a/serv.core b/serv.core index a2524d7..0be0717 100644 --- a/serv.core +++ b/serv.core @@ -9,6 +9,7 @@ filesets: - rtl/serv_params.vh : {is_include_file : true} - rtl/shift_reg.v - rtl/ser_add.v + - rtl/ser_eq.v - rtl/serv_alu.v - rtl/serv_ctrl.v - rtl/serv_decode.v @@ -16,7 +17,7 @@ filesets: - rtl/serv_regfile.v - rtl/serv_top.v file_type : verilogSource - depend : [wb_ram] + depend : [wb_ram, "yosys:techlibs:ice40"] ser_add_tb: files: