diff --git a/bench/serv_top_tb.v b/bench/serv_top_tb.v index d0e108b..0280254 100644 --- a/bench/serv_top_tb.v +++ b/bench/serv_top_tb.v @@ -76,11 +76,11 @@ module serv_top_tb; 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 + if (((d_ca_en & d_ca_cmd & (d_ca_adr == 32'h10000000)) |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; + catch_write <= 1'b0; end end vlog_tb_utils vtu(); diff --git a/rtl/serv_alu.v b/rtl/serv_alu.v index 10da7c6..74a33f7 100644 --- a/rtl/serv_alu.v +++ b/rtl/serv_alu.v @@ -27,6 +27,7 @@ module serv_alu reg en_r; wire v; reg msb_lt = 1'b0; + reg init_r; shift_reg #(.LEN (5)) shamt_reg @@ -92,6 +93,7 @@ module serv_alu assign o_rd = (i_rd_sel == ALU_RESULT_ADD) ? result_add : (i_rd_sel == ALU_RESULT_SR) ? result_sh : + (i_rd_sel == ALU_RESULT_LT) ? (result_lt2 & init_r & ~i_init): 1'bx; always @(posedge clk) begin @@ -100,9 +102,9 @@ module serv_alu msb_lt <= i_cmp_uns ? (~i_rs1 & i_op_b) : (i_rs1 & ~i_op_b); end -// result_lt <= /*v^*/result_add; - en_r <= i_en; + init_r <= i_init; + end endmodule diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index b4164ae..ad01748 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -25,7 +25,7 @@ module serv_decode output o_mem_en, output o_mem_cmd, output o_mem_init, - output o_mem_dat_valid, + output reg o_mem_dat_valid, input i_mem_busy, output [2:0] o_funct3, output reg o_imm, @@ -116,9 +116,9 @@ module serv_decode end assign o_alu_shamt_en = (state == SH_INIT) & (cnt < 5); - assign o_alu_rd_sel = (o_funct3 == 3'b000) ? ALU_RESULT_ADD : + assign o_alu_rd_sel = (o_funct3 == 3'b000) ? ALU_RESULT_ADD : (o_funct3[2:1] == 2'b01) ? ALU_RESULT_LT : - (o_funct3 == 3'b101) ? ALU_RESULT_SR : + (o_funct3 == 3'b101) ? ALU_RESULT_SR : 2'bxx; assign o_mem_en = mem_op & cnt_en; @@ -141,9 +141,17 @@ module serv_decode (opcode == OP_OP) ? 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; - + always @(o_funct3, cnt) + if (o_mem_init) + o_mem_dat_valid = 1'bx; + else + casez(o_funct3[1:0]) + 2'b00 : o_mem_dat_valid = (cnt < 8); + 2'b01 : o_mem_dat_valid = (cnt < 16); + 2'b10 : o_mem_dat_valid = 1'b1; + default: o_mem_dat_valid = 1'bx; + endcase + wire [4:0] opcode = i_i_rd_dat[6:2]; @@ -201,6 +209,7 @@ module serv_decode IDLE : begin if (go) state <= (opcode == OP_BRANCH) ? COMPARE : + ((opcode == OP_OPIMM) & (o_funct3[2:1] == 2'b01)) ? COMPARE : mem_op ? MEM_INIT : shift_op ? SH_INIT : RUN; end diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index 972278c..bf8dcaa 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -31,6 +31,7 @@ module serv_mem_if reg init_r; reg en_r; + reg en_2r; wire adr; reg [31:0] dat = 32'd0; reg signbit = 1'b0; @@ -47,7 +48,7 @@ module serv_mem_if shift_reg #(32) shift_reg_adr ( .clk (i_clk), - .i_en (i_en), + .i_en (i_init), .i_d (adr), .o_q (o_d_ca_adr[0]), .o_par (o_d_ca_adr[31:1]) @@ -55,24 +56,44 @@ module serv_mem_if assign o_d_ca_cmd = i_cmd; - wire is_signed = i_funct3[2]; - assign o_rd = i_dat_valid ? dat[0] : is_signed & signbit; + wire is_signed = ~i_funct3[2]; + assign o_rd = i_dat_valid ? dat[0] : signbit & is_signed; assign o_d_rd_rdy = !i_en; //Likely bug, but probably doesn't matter 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[1:0]; + 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}}} : 4'd1 << bytepos; - + reg [1:0] bytepos; + reg [4:0] cnt = 5'd0; + reg dat_en; + + always @(i_funct3, cnt, bytepos) + casez(i_funct3[1:0]) + 2'b1? : dat_en = 1'b1; + 2'b?1 : dat_en = bytepos[1] ? (cnt<16) : 1'b1; + 2'b00 : dat_en = (bytepos == 2'd3) ? (cnt <8) : + (bytepos == 2'd2) ? (cnt < 16) : + (bytepos == 2'd1) ? (cnt < 24) : 1'b1; + endcase + always @(posedge i_clk) begin - signbit <= dat[0]; + cnt <= cnt + i_init; + + if (i_en & !en_r) + bytepos[0] <= adr; + if (en_r & !en_2r) + bytepos[1] <= adr; + + if (i_dat_valid) + signbit <= dat[0]; if (i_en & i_init) o_busy <= 1'b1; @@ -90,6 +111,7 @@ module serv_mem_if end en_r <= i_en; + en_2r <= en_r; init_r <= i_init; if (ca_en) o_d_ca_vld <= 1'b0; @@ -102,7 +124,7 @@ module serv_mem_if else if (init_r & !i_init) o_d_dm_vld <= i_cmd; - if (i_en) + if (i_en & dat_en) dat <= {i_rs2,dat[31:1]}; end endmodule