mirror of
https://github.com/olofk/serv.git
synced 2026-01-13 23:25:57 +00:00
184 lines
4.1 KiB
Verilog
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
|