blob: e3668d7affe99691d906e93a41b17719edd6a5f1 [file] [log] [blame] [edit]
`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_mret,
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_wreq,
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"
/*
********** Write side ***********
*/
reg [4:0] wcnt;
reg wgo;
wire [3:0] wslot = wcnt[4:1];
wire wport = wcnt[0];
wire wdata0 = i_trap ? i_mtval : i_rd;
wire wdata1 = i_trap ? i_mepc : i_csr;
reg wdata0_r;
reg wdata1_r;
reg wdata1_2r;
wire [1:0] wdata = !wport ?
{wdata0 , wdata0_r} :
{wdata1_r, wdata1_2r};
//port 0 rd mtval
//port 1 csr mepc
//mepc 100010
//mtval 100011
//csr 1000xx
//rd 0xxxxx
wire [5:0] wreg0 = i_trap ? {4'b1000,CSR_MTVAL} : {1'b0,i_rd_waddr};
wire [5:0] wreg1 = i_trap ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr};
wire [5:0] wreg = wport ? wreg1 : wreg0;
wire [9:0] waddr = {wreg, wslot};
wire wen = wgo & (i_trap | (wport ? i_csr_en : i_rd_wen & run_r));
reg wreq_r;
reg run_r;
always @(posedge i_clk) begin
wreq_r <= i_wreq | o_rgnt;
wdata0_r <= wdata0;
wdata1_r <= wdata1;
wdata1_2r <= wdata1_r;
run_r <= i_run;
if (wgo)
wcnt <= wcnt+5'd1;
if (wreq_r)
wgo <= 1'b1;
if (wcnt == 5'b11111)
wgo <= 1'b0;
if (i_rst) begin
wcnt <= 5'd0;
end
end
/*
********** Read side ***********
*/
//0 : RS1
//1 : RS2 / CSR
reg [4:0] rcnt;
wire [3:0] rslot = rcnt[4:1];
wire rport = rcnt[0];
wire [5:0] rreg0 = {1'b0, i_rs1_raddr};
wire [5:0] rreg1 =
i_trap ? {4'b1000, CSR_MTVEC} :
i_mret ? {4'b1000, CSR_MEPC} :
i_csr_en ? {4'b1000, i_csr_addr} :
{1'b0,i_rs2_raddr};
wire [5:0] rreg = rport ? rreg1 : rreg0;
wire [9:0] raddr = {rreg, rslot};
reg [1:0] rdata;
reg [1:0] rdata0;
reg rdata1;
assign o_rs1 = !rport ? rdata0[0] : rdata0[1];
assign o_rs2 = rport ? rdata1 : rdata[0];
assign o_csr = o_rs2 & i_csr_en;
assign o_csr_pc = o_rs2;
reg rreq_r;
always @(posedge i_clk) begin
rcnt <= rcnt+5'd1;
if (i_rreq)
rcnt <= 5'd0;
rreq_r <= i_rreq;
o_rgnt <= rreq_r;
if (rport)
rdata0 <= rdata;
if (!rport)
rdata1 <= rdata[1];
if (i_rst) begin
o_rgnt <= 1'b0;
rreq_r <= 1'b0;
end
end
reg [1:0] memory [0:575];
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<512;i=i+1)
memory[i] = 2'd0;
`endif
endmodule