From 42ac1e5e4d8080b337904c5e05f7442f596c3333 Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Mon, 18 Mar 2019 12:16:31 +0100 Subject: [PATCH] Store CSR in RF RAM Since FPGA uses fixed-size RAM, it's better in most cases to store the CSR in unused memory positions in that RAM. Since the decoding is made more complex, the old register file implementation is kept around since that is more efficient when we don't want CSR and potentially when the FPGA support hardware shift registers. --- rtl/serv_csr.v | 20 +++--- rtl/serv_mpram.v | 173 +++++++++++++++++++++++++++++++++++++++++++++++ rtl/serv_top.v | 39 ++++++++++- serv.core | 1 + 4 files changed, 218 insertions(+), 15 deletions(-) create mode 100644 rtl/serv_mpram.v diff --git a/rtl/serv_csr.v b/rtl/serv_csr.v index 7107292..ffabb05 100644 --- a/rtl/serv_csr.v +++ b/rtl/serv_csr.v @@ -4,13 +4,16 @@ module serv_csr input wire i_clk, input wire [4:0] i_cnt, input wire [3:0] i_cnt_r, + //From mpram + input wire i_rf_csr_out, + //to mpram + output wire o_csr_in, + //Stuff input wire i_mtip, output wire o_timer_irq_en, input wire i_mstatus_en, input wire i_mie_en, - input wire i_mtvec_en, input wire i_mip_en, - input wire i_mscratch_en, input wire i_mepc_en, input wire i_mcause_en, input wire i_mtval_en, @@ -38,16 +41,13 @@ module serv_csr reg mstatus; reg mstatus_mie; reg mie_mtie; - reg [31:0] mtvec = 32'h0; - reg [31:0] mscratch; reg [31:0] mepc; reg mcause31; reg [3:0] mcause3_0; wire mcause; reg [31:0] mtval; - wire csr_in; wire csr_out; @@ -58,8 +58,7 @@ module serv_csr 1'bx; assign csr_out = (i_mstatus_en & mstatus) | - (i_mtvec_en & mtvec[0]) | - (i_mscratch_en & mscratch[0]) | + i_rf_csr_out | (i_mepc_en & mepc[0]) | (i_mcause_en & mcause) | (i_mtval_en & mtval[0]); @@ -72,6 +71,8 @@ module serv_csr ((i_cnt[4:2] == 3'd7) & i_cnt_r[3]) ? mcause31 //[31] : 1'b0; + assign o_csr_in = csr_in; + always @(posedge i_clk) begin if (i_mstatus_en & (i_cnt[4:2] == 3'd0) & i_cnt_r[3]) mstatus_mie <= csr_in; @@ -85,11 +86,6 @@ module serv_csr mcause31 <= i_mtip & o_timer_irq_en; mcause3_0 <= (i_mtip & o_timer_irq_en) ? 4'd7 : i_mcause[3:0]; end - if (i_mscratch_en) - mscratch <= {csr_in, mscratch[31:1]}; - - if (i_mtvec_en) - mtvec <= {csr_in, mtvec[31:1]}; if (i_mepc_en | i_trap) mepc <= {i_trap ? i_pc : csr_in, mepc[31:1]}; diff --git a/rtl/serv_mpram.v b/rtl/serv_mpram.v new file mode 100644 index 0000000..c2b4b9c --- /dev/null +++ b/rtl/serv_mpram.v @@ -0,0 +1,173 @@ +`default_nettype none +module serv_mpram + ( + input wire i_clk, + input wire i_rst, + //MEPC write port + input wire i_mepc_wen, + input wire i_mepc, + //MTVAL write port + input wire i_mtval_wen, + input wire i_mtval, + //CSR interface + input wire i_csr_mscratch_en, + input wire i_csr_mtvec_en, + input wire i_csr, + output wire o_csr, + //RD write port + input wire i_rd_wen, + input wire [4:0] i_rd_waddr, + input wire i_rd, + + input wire i_rreq, + output reg o_rgnt, + //RS1 read port + input wire [4:0] i_rs1_raddr, + output wire o_rs1, + //RS2 read port + input wire [4:0] i_rs2_raddr, + output wire o_rs2); + + reg [1:0] csr_addr; + wire csr_en = i_csr_mscratch_en|i_csr_mtvec_en; + + + wire [8:0] waddr; + + reg [4:0] wdata0; + reg [5:0] wdata1; + reg [6:0] wdata2; + reg [7:0] wdata3; + + wire [3:0] wdata; + + wire wen; + reg [3:0] wen_r; + + reg [3:0] wcnt_lo; + reg [2:0] wcnt_hi; + + assign wdata = wcnt_lo[0] ? wdata0[3:0] : + wcnt_lo[1] ? wdata1[3:0] : + wcnt_lo[2] ? wdata2[3:0] : + /*wcnt_lo[3] ?*/ wdata3[3:0]; + assign wen = !wgo_r & |(wen_r & wcnt_lo); + + reg [4:0] rd_waddr; + //mepc 100000 + //mtval 100011 + //csr 1000xx + //rd 0xxxxx + assign waddr[8] = !wcnt_lo[3]; + assign waddr[7:5] = wcnt_lo[3] ? rd_waddr[4:2] : 3'b000; + assign waddr[4:3] = wcnt_lo[3] ? rd_waddr[1:0] : + wcnt_lo[2] ? csr_addr : + wcnt_lo[1] ? 2'b11 : 2'b00; + assign waddr[2:0] = wcnt_hi; + + wire wgo = !(|wcnt_lo) & |({i_rd_wen,csr_en,i_mtval_wen,i_mepc_wen}); + + reg wgo_r; + + always @(posedge i_clk) begin + if (wgo) begin + wgo_r <= 1'b1; + wen_r <= {i_rd_wen,csr_en,i_mtval_wen,i_mepc_wen}; + rd_waddr <= i_rd_waddr; + end + wdata0 <= {i_mepc,wdata0[4:1]}; + wdata1 <= {i_mtval,wdata1[5:1]}; + wdata2 <= {i_csr,wdata2[6:1]}; + wdata3 <= {i_rd,wdata3[7:1]}; + wcnt_lo <= {wcnt_lo[2:0],wcnt_lo[3] | wgo}; + if (wcnt_lo[3]) begin + wcnt_hi <= wcnt_hi + 1; + if (wcnt_hi == 3'd7) begin + wgo_r <= !wgo_r; + wcnt_lo[0] <= wgo_r; + wcnt_hi <= wcnt_hi + {2'b00,wgo_r}; + end + end + if (i_rst) begin + wgo_r <= 1'b0; + wcnt_lo <= 4'd0; + wcnt_hi <= 3'd7; + end + end + + //0 : RS1 + //1 : RS2 + //2 : CSR + reg [2:0] rcnt_hi; + reg [3:0] rcnt_lo; + + wire [8:0] raddr; + + reg [3:0] rdata; + + reg [5:0] rdata0; + reg [4:0] rdata1; + reg [3:0] rdata2; + //reg [3:0] rdata3; + + reg [2:0] rreq; + + + always @(posedge i_clk) begin + {o_rgnt,rreq} <= {rreq[2:0],i_rreq}; + if (rcnt_lo[3]) + rcnt_hi <= rcnt_hi + 1; + if (i_rreq) begin + rcnt_lo <= 4'd1; + rcnt_hi <= 3'd0; + csr_addr <= {1'b0,i_csr_mtvec_en}; + end else + rcnt_lo <= {rcnt_lo[2:0],rcnt_lo[3]}; + + + rdata0[4:0] <= rdata0[5:1]; + rdata1[3:0] <= rdata1[4:1]; + rdata2[2:0] <= rdata2[3:1]; + //rdata3[2:0] <= rdata3[3:1]; + + if (rcnt_lo[1]) rdata0[5:2] <= rdata; + if (rcnt_lo[2]) rdata1[4:1] <= rdata; + if (rcnt_lo[3]) rdata2[3:0] <= rdata; + //if (rcnt_lo[0]) rdata3[3:0] <= rdata; + + if (i_rst) begin + o_rgnt <= 1'b0; + rreq <= 3'd0; + end + end + + assign raddr[8] = rcnt_lo[2]; + assign raddr[7:5] = rcnt_lo[0] ? i_rs1_raddr[4:2] : + rcnt_lo[1] ? i_rs2_raddr[4:2] : 3'd0; + assign raddr[4:3] = rcnt_lo[0] ? i_rs1_raddr[1:0] : + rcnt_lo[1] ? i_rs2_raddr[1:0] : csr_addr; + assign raddr[2:0] = rcnt_hi; + + assign o_rs1 = rdata0[0]; + assign o_rs2 = rdata1[0]; + assign o_csr = rdata2[0] & csr_en; + + reg [3:0] memory [0:511]; + + always @(posedge i_clk) begin + if (wen) +`ifdef RISCV_FORMAL + if (!i_rst) +`endif + memory[waddr] <= wdata; + rdata <= memory[raddr]; + end + +`ifdef RISCV_FORMAL + integer i; + initial + for (i=0;i<256;i=i+1) + memory[i] = 4'd0; +`endif + +endmodule diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 8a2ec70..580b966 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -277,7 +277,7 @@ module serv_top .o_sh_done (alu_sh_done), .i_rd_sel (alu_rd_sel), .o_rd (alu_rd)); - +/* serv_regfile regfile ( .i_clk (clk), @@ -291,6 +291,39 @@ module serv_top .i_rs2_addr (rs2_addr), .o_rs1 (rs1), .o_rs2 (rs2)); +*/ + wire csr_in; + wire rf_csr_out; + + serv_mpram regfile + ( + .i_clk (clk), + .i_rst (i_rst), + //MEPC write port + .i_mepc_wen (1'b0), + .i_mepc (1'b0), + //MTVAL write port + .i_mtval_wen (1'b0), + .i_mtval (1'b0), + //CSR write port + .i_csr_mscratch_en (csr_mscratch_en), + .i_csr_mtvec_en (csr_mtvec_en), + .i_csr (csr_in), + //RD write port + .i_rd_wen (rd_en & (|rd_addr)), + .i_rd_waddr (rd_addr), + .i_rd (rd), + + .i_rreq (i_ibus_ack), + .o_rgnt (rf_ready), + //RS1 read port + .i_rs1_raddr (rs1_addr), + .o_rs1 (rs1), + //RS2 read port + .i_rs2_raddr (rs2_addr), + .o_rs2 (rs2), + //CSR read port + .o_csr (rf_csr_out)); serv_mem_if mem_if ( @@ -319,13 +352,13 @@ module serv_top .i_clk (clk), .i_cnt (cnt), .i_cnt_r (cnt_r), + .i_rf_csr_out (rf_csr_out), + .o_csr_in (csr_in), .i_mtip (i_timer_irq), .o_timer_irq_en ( timer_irq_en), .i_mstatus_en (csr_mstatus_en), .i_mie_en (csr_mie_en ), - .i_mtvec_en (csr_mtvec_en ), .i_mip_en (csr_mip_en ), - .i_mscratch_en (csr_mscratch_en), .i_mepc_en (csr_mepc_en ), .i_mcause_en (csr_mcause_en ), .i_mtval_en (csr_mtval_en ), diff --git a/serv.core b/serv.core index fd7e74b..5de8795 100644 --- a/serv.core +++ b/serv.core @@ -17,6 +17,7 @@ filesets: - rtl/serv_decode.v - rtl/serv_mem_if.v - rtl/serv_regfile.v + - rtl/serv_mpram.v - rtl/serv_top.v file_type : verilogSource