1
0
mirror of https://github.com/olofk/serv.git synced 2026-01-13 23:25:57 +00:00
olofk.serv/rtl/serv_mpram.v
2019-09-14 22:18:03 +02:00

184 lines
4.1 KiB
Verilog

`default_nettype none
module serv_mpram
(
input wire i_clk,
input wire i_rst,
input wire i_run,
//Trap interface
input wire i_trap,
input wire i_mepc,
input wire i_mtval,
output wire o_csr_pc,
//CSR interface
input wire i_csr_en,
input wire [1:0] i_csr_addr,
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);
`include "serv_params.vh"
wire [8:0] waddr;
reg [4:0] wdata0;
reg [5:0] wdata1;
wire [3:0] wdata;
wire wen;
reg [1:0] wen_r;
reg [3:0] wcnt_lo;
reg [2:0] wcnt_hi;
reg wgo_r;
assign wdata = wcnt_lo[0] ? wdata0[3:0] : wdata1[3:0];
assign wen = !wgo_r & |(wen_r & wcnt_lo[1:0]);
reg [4:0] rd_waddr;
//port 0 rd mtval
//port 1 csr mepc
//mepc 100010
//mtval 100011
//csr 1000xx
//rd 0xxxxx
wire [5:0] waddr0 = trap_3r ? {4'b1000,CSR_MTVAL} : {1'b0,rd_waddr};
wire [5:0] waddr1 = trap_3r ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr};
assign waddr[8:3] = wcnt_lo[0] ? waddr0 : waddr1;
// assign waddr[8] = wcnt_lo[1] | i_trap;
// assign waddr[7:5] = (wcnt_lo[1] | i_trap) ? 3'b000 : rd_waddr[4:2];
// assign waddr[4:3] = wcnt_lo[0] ? (i_trap ? CSR_MTVAL : rd_waddr[1:0]) :
// (i_trap ? CSR_MEPC : i_csr_addr);
assign waddr[2:0] = wcnt_hi;
wire wgo = !(|wcnt_lo) & ((i_run & (i_rd_wen | i_csr_en)) | i_trap);
reg trap_r;
reg trap_2r;
reg trap_3r;
always @(posedge i_clk) begin
trap_r <= i_trap;
trap_2r <= trap_r;
trap_3r <= trap_2r;
if (wgo) begin
wgo_r <= 1'b1;
wen_r <= {(i_run & i_csr_en)|i_trap,(i_rd_wen & i_run)|i_trap};
rd_waddr <= i_rd_waddr;
end
wdata0 <= {i_trap ? i_mtval : i_rd ,wdata0[4:1]};
wdata1 <= {i_trap ? i_mepc : i_csr,wdata1[5: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;
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] :
i_trap ? CSR_MTVEC : i_csr_addr;
assign raddr[2:0] = rcnt_hi;
assign o_rs1 = rdata0[0];
assign o_rs2 = rdata1[0];
assign o_csr = rdata2[0] & i_csr_en;
assign o_csr_pc = rdata2[0];
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
`define SERV_CLEAR_RAM
`endif
`ifdef SERV_CLEAR_RAM
integer i;
initial
for (i=0;i<256;i=i+1)
memory[i] = 4'd0;
`endif
endmodule