diff --git a/bench/serv_top_tb.v b/bench/serv_top_tb.v index 281ec88..d0e108b 100644 --- a/bench/serv_top_tb.v +++ b/bench/serv_top_tb.v @@ -63,9 +63,28 @@ module serv_top_tb; .rd_dat_o (d_rd_dat), .rd_vld_o (d_rd_vld), .rd_rdy_i (d_rd_rdy)); + + reg catch_write = 1'b0; + + reg dbg = 1'b0; + + wire d_ca_en = d_ca_vld & d_ca_rdy; + wire d_dm_en = d_dm_vld & d_dm_rdy; + always @(posedge clk) begin + dbg <= 1'b0; + + if (d_ca_en & d_ca_cmd & (d_ca_adr == 32'h10000000)) + catch_write <= 1'b1; + if (catch_write & d_dm_en & d_dm_msk[0]) begin + dbg <= 1'b1; + $write("%c", d_dm_dat[7:0]); + $fflush(); + catch_write = 1'b0; + end + end vlog_tb_utils vtu(); - + serv_top #(.RESET_PC (32'd8)) dut diff --git a/rtl/ser_eq.v b/rtl/ser_eq.v index f143973..4c530ef 100644 --- a/rtl/ser_eq.v +++ b/rtl/ser_eq.v @@ -1,15 +1,19 @@ +`default_nettype none module ser_eq ( input clk, input a, input b, input clr, - output q); + output reg o_q); reg eq = 1'b1; - assign q = eq & (a == b); - always @(posedge clk) - eq <= q | clr; + wire q = eq & (a == b); + always @(posedge clk) begin + eq <= q | clr; + if (!clr) + o_q <= q; + end endmodule diff --git a/rtl/ser_shift.v b/rtl/ser_shift.v new file mode 100644 index 0000000..2ec11b5 --- /dev/null +++ b/rtl/ser_shift.v @@ -0,0 +1,43 @@ +`default_nettype none +module ser_shift + ( + input i_clk, + input i_load, + input [4:0] i_shamt, + input i_sr, + input i_d, + output o_q); + + wire [31:0] shiftreg; + + reg signbit = 1'b0; + reg wrapped = 1'b0; + reg [4:0] cnt = 5'd0; + + shift_reg #(.LEN (32)) sh_reg + (.clk (i_clk), + .i_en (i_load), + .i_d (i_d), + .o_q (shiftreg[0]), + .o_par (shiftreg[31:1])); + + always @(posedge i_clk) begin + cnt <= cnt + 1; + if (i_load) begin + cnt <= i_shamt; + wrapped <= 1'b0; + end + + if (cnt == 31) begin + signbit <= shiftreg[cnt]; + wrapped <= 1'b1; + end + + end + + assign o_q = wrapped ? signbit : shiftreg[cnt]; + +endmodule + + + diff --git a/rtl/serv_alu.v b/rtl/serv_alu.v index 18dabfe..98c7216 100644 --- a/rtl/serv_alu.v +++ b/rtl/serv_alu.v @@ -3,27 +3,43 @@ module serv_alu ( input clk, input i_en, + input [2:0] i_op, input [2:0] i_funct3, input i_rs1, input i_op_b, - input i_cmp_en, - output o_cmp, + input i_init, + output o_cmp, + input i_shamt_en, output o_rd); - localparam [2:0] - ADDI = 3'b000, - SLTI = 3'b010, - SLTIU = 3'b011, - XORI = 3'b100, - ORI = 3'b110, - ANDI = 3'b111; +`include "serv_params.vh" localparam[2:0] - BEQ = 3'b000; + BEQ = 3'b000, + BNE = 3'b001; wire result_add; wire result_eq; + wire result_sh; + wire [4:0] shamt; + + shift_reg #(.LEN (5)) shamt_reg + (.clk (clk), + .i_en (i_shamt_en), + .i_d (i_op_b), + .o_q (shamt[0]), + .o_par (shamt[4:1])); + + ser_shift shift + ( + .i_clk (clk), + .i_load (i_init), + .i_shamt (shamt), + .i_sr (/*FIXME*/), + .i_d (i_rs1), + .o_q (result_sh)); + ser_add ser_add ( .clk (clk), @@ -32,19 +48,20 @@ 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; + .clr (!i_init), + .o_q (result_eq)); - assign o_rd = (i_funct3 == ADDI) ? result_add : 1'b0; + assign o_cmp = (i_funct3 == BEQ) ? result_eq : + (i_funct3 == BNE) ? ~result_eq : 1'bx; + + assign o_rd = (i_op == ALU_OP_ADD) ? result_add : + (i_op == ALU_OP_SR) ? result_sh : + 1'bx; endmodule diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index c212e0d..84c036d 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -11,8 +11,11 @@ module serv_decode output o_rf_rs_en, output [4:0] o_rf_rs1_addr, output [4:0] o_rf_rs2_addr, - output o_alu_cmp_en, + output o_alu_en, + output [2:0] o_alu_op, + output o_alu_init, input i_alu_cmp, + output o_alu_shamt_en, output o_mem_en, output o_mem_cmd, output o_mem_init, @@ -26,13 +29,13 @@ module serv_decode `include "serv_params.vh" - localparam [2:0] IDLE = 3'd0, COMPARE = 3'd1, - MEM_INIT = 3'd2, - MEM_WAIT = 3'd3, - RUN = 3'd4; + SH_INIT = 3'd2, + MEM_INIT = 3'd3, + MEM_WAIT = 3'd4, + RUN = 3'd5; localparam [4:0] OP_LOAD = 5'b00000, @@ -48,19 +51,33 @@ module serv_decode wire running; wire mem_op; + wire shift_op; + assign mem_op = (opcode == OP_LOAD) | (opcode == OP_STORE); + assign shift_op = (opcode == OP_OPIMM) & (o_funct3[1:0] == 2'b01); assign o_ctrl_en = running; 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_rf_rd_en = running & + (opcode != OP_STORE) & + (opcode != OP_BRANCH); + + assign o_rf_rs_en = cnt_en /*(running & (opcode == OP_OPIMM)) | + (state == SH_INIT) | + (state == MEM_INIT)*/; + wire sub = 1'b0; //FIXME + + assign o_alu_en = cnt_en; + assign o_alu_op = (o_funct3 == 3'b000) ? {1'b0, sub, 1'b0} : + (o_funct3 == 3'b101) ? ALU_OP_SR : + 3'bxxx; + + assign o_alu_init = (state == COMPARE) | + (state == SH_INIT); + assign o_alu_shamt_en = (state == SH_INIT) & (cnt < 5); + assign o_mem_en = mem_op & cnt_en; assign o_mem_cmd = (opcode == OP_STORE); @@ -83,9 +100,10 @@ module serv_decode assign o_rd_source = (opcode == OP_JAL) ? RD_SOURCE_CTRL : (opcode == OP_OPIMM) ? RD_SOURCE_ALU : - (opcode == OP_LUI) ? RD_SOURCE_IMM : 2'b00; + (opcode == OP_LUI) ? RD_SOURCE_IMM : + (opcode == OP_LOAD) ? RD_SOURCE_MEM : 2'bxx; - always @(cnt, opcode) begin + always @(cnt, opcode, i_i_rd_dat) begin o_imm = 1'bx; if (opcode == OP_JAL) if (cnt > 19) o_imm = i_i_rd_dat[31]; @@ -119,6 +137,7 @@ module serv_decode wire cnt_en = (state == RUN) | (state == COMPARE) | + (state == SH_INIT) | (state == MEM_INIT); wire cnt_done = cnt == 31; @@ -129,8 +148,13 @@ module serv_decode case (state) IDLE : begin if (go) - state <= (opcode == OP_BRANCH) ? COMPARE : - mem_op ? MEM_INIT : RUN; + state <= (opcode == OP_BRANCH) ? COMPARE : + mem_op ? MEM_INIT : + shift_op ? SH_INIT : RUN; + end + SH_INIT : begin + if (cnt_done) + state <= RUN; end COMPARE : begin if (cnt_done) diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index a86d522..8c4483f 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -29,6 +29,7 @@ module serv_mem_if wire dm_en = o_d_dm_vld & i_d_dm_rdy; wire rd_en = i_d_rd_vld & o_d_rd_rdy; + reg init_r; reg en_r; wire adr; reg [31:0] dat = 32'd0; @@ -61,7 +62,7 @@ module serv_mem_if 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 [1:0] bytepos = o_d_ca_adr[1:0]; wire upper_half = bytepos[1]; assign o_d_dm_dat = dat; @@ -88,15 +89,16 @@ module serv_mem_if end en_r <= i_en; + init_r <= i_init; if (ca_en) o_d_ca_vld <= 1'b0; - else if (en_r & !i_en) begin + else if (init_r & !i_init) begin //Optimize? o_d_ca_vld <= 1'b1; end if (dm_en) o_d_dm_vld <= 1'b0; - else if (en_r & !i_en) + else if (init_r & !i_init) o_d_dm_vld <= i_cmd; if (i_en) diff --git a/rtl/serv_params.vh b/rtl/serv_params.vh index d911e2e..802aa07 100644 --- a/rtl/serv_params.vh +++ b/rtl/serv_params.vh @@ -12,3 +12,14 @@ localparam [0:0] OP_B_SOURCE_IMM = 1'd0, OP_B_SOURCE_RS2 = 1'd1; +localparam[2:0] + ALU_OP_ADD = 3'd0, + ALU_OP_SL = 3'd1, + ALU_OP_SUB = 3'd2, + ALU_OP_SLT = 3'd3, + ALU_OP_XOR = 3'd4, + ALU_OP_SR = 3'd5, + ALU_OP_OR = 3'd6, + ALU_OP_AND = 3'd7; + + diff --git a/rtl/serv_top.v b/rtl/serv_top.v index ac29e87..32ffff6 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -1,6 +1,5 @@ `default_nettype none -`define RISCV_FORMAL `define RISCV_FORMAL_NRET 1 `define RISCV_FORMAL_XLEN 32 `define RISCV_FORMAL_ILEN 32 @@ -70,8 +69,11 @@ module serv_top wire [2:0] funct3; - wire alu_cmp_en; + wire alu_en; + wire [2:0] alu_op; + wire alu_init; wire alu_cmp; + wire alu_shamt_en; wire rs1; wire rs2; @@ -100,8 +102,11 @@ module serv_top .o_ctrl_en (ctrl_en), .o_ctrl_jump (jump), .o_funct3 (funct3), - .o_alu_cmp_en (alu_cmp_en), + .o_alu_en (alu_en), + .o_alu_op (alu_op), + .o_alu_init (alu_init), .i_alu_cmp (alu_cmp), + .o_alu_shamt_en (alu_shamt_en), .o_rf_rd_en (rd_en), .o_rf_rd_addr (rd_addr), .o_rf_rs_en (rs_en), @@ -133,24 +138,27 @@ module serv_top assign offset = (offset_source == OFFSET_SOURCE_IMM) ? imm : rs1; assign rd = (rd_source == RD_SOURCE_CTRL) ? ctrl_rd : - (rd_source == RD_SOURCE_ALU) ? alu_rd : - (rd_source == RD_SOURCE_IMM) ? imm : - (rd_source == RD_SOURCE_MEM) ? mem_rd : 1'b0; + (rd_source == RD_SOURCE_ALU) ? alu_rd : + (rd_source == RD_SOURCE_IMM) ? imm : + (rd_source == RD_SOURCE_MEM) ? mem_rd : 1'bx; assign op_b = (op_b_source == OP_B_SOURCE_IMM) ? imm : - 1'b0; + (op_b_source == OP_B_SOURCE_RS2) ? rs2 : + 1'bx; serv_alu alu ( - .clk (clk), - .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)); + .clk (clk), + .i_en (alu_en), + .i_op (alu_op), + .i_funct3 (funct3), + .i_init (alu_init), + .o_cmp (alu_cmp), + .i_shamt_en (alu_shamt_en), + .i_rs1 (rs1), + .i_op_b (op_b), + .o_rd (alu_rd)); serv_regfile regfile ( diff --git a/serv.core b/serv.core index 0be0717..ef2695e 100644 --- a/serv.core +++ b/serv.core @@ -10,6 +10,7 @@ filesets: - rtl/shift_reg.v - rtl/ser_add.v - rtl/ser_eq.v + - rtl/ser_shift.v - rtl/serv_alu.v - rtl/serv_ctrl.v - rtl/serv_decode.v @@ -77,4 +78,10 @@ targets: serv_top_tb: default_tool: icarus filesets : [core, serv_top_tb] + parameters : [RISCV_FORMAL=true] toplevel : serv_top_tb + +parameters: + RISCV_FORMAL: + datatype : bool + paramtype : vlogdefine