1
0
mirror of https://github.com/olofk/serv.git synced 2026-04-26 04:08:45 +00:00
Files
olofk.serv/rtl/serv_rf_ram_if.v
Olof Kindgren c1b8471678 Add reset_strategy parameter
The reset_strategy parameter controls how much reset to apply to
SERV. It can be set to MINI for the default behaviour, or NONE to
only apply reset where absolutely needed and rely on POR to clear
FFs
2020-11-10 15:16:19 +01:00

166 lines
3.6 KiB
Verilog

`default_nettype none
module serv_rf_ram_if
#(parameter width=8,
parameter reset_strategy="MINI",
parameter csr_regs=4,
parameter depth=32*(32+csr_regs)/width,
parameter l2w = $clog2(width))
(
//SERV side
input wire i_clk,
input wire i_rst,
input wire i_wreq,
input wire i_rreq,
output wire o_ready,
input wire [$clog2(32+csr_regs)-1:0] i_wreg0,
input wire [$clog2(32+csr_regs)-1:0] i_wreg1,
input wire i_wen0,
input wire i_wen1,
input wire i_wdata0,
input wire i_wdata1,
input wire [$clog2(32+csr_regs)-1:0] i_rreg0,
input wire [$clog2(32+csr_regs)-1:0] i_rreg1,
output wire o_rdata0,
output wire o_rdata1,
//RAM side
output wire [$clog2(depth)-1:0] o_waddr,
output wire [width-1:0] o_wdata,
output wire o_wen,
output wire [$clog2(depth)-1:0] o_raddr,
input wire [width-1:0] i_rdata);
reg rgnt;
assign o_ready = rgnt | i_wreq;
/*
********** Write side ***********
*/
reg [4:0] wcnt;
reg wgo;
reg [width-2:0] wdata0_r;
reg [width-1:0] wdata1_r;
reg wen0_r;
reg wen1_r;
wire wtrig0;
wire wtrig1;
generate if (width == 2) begin
assign wtrig0 = ~wcnt[0];
assign wtrig1 = wcnt[0];
end else begin
reg wtrig0_r;
always @(posedge i_clk) wtrig0_r <= wtrig0;
assign wtrig0 = (wcnt[l2w-1:0] == {{l2w-1{1'b1}},1'b0});
assign wtrig1 = wtrig0_r;
end
endgenerate
assign o_wdata = wtrig1 ?
wdata1_r :
{i_wdata0, wdata0_r};
wire [$clog2(32+csr_regs)-1:0] wreg = wtrig1 ? i_wreg1 : i_wreg0;
generate if (width == 32)
assign o_waddr = wreg;
else
assign o_waddr = {wreg, wcnt[4:l2w]};
endgenerate
assign o_wen = wgo & ((wtrig0 & wen0_r) | (wtrig1 & wen1_r));
reg wreq_r;
generate if (width > 2)
always @(posedge i_clk) wdata0_r <= {i_wdata0, wdata0_r[width-2:1]};
else
always @(posedge i_clk) wdata0_r <= i_wdata0;
endgenerate
always @(posedge i_clk) begin
wen0_r <= i_wen0;
wen1_r <= i_wen1;
wreq_r <= i_wreq | rgnt;
wdata1_r <= {i_wdata1,wdata1_r[width-1:1]};
if (wgo)
wcnt <= wcnt+5'd1;
if (wreq_r) begin
wgo <= 1'b1;
end
if (wcnt == 5'b11111)
wgo <= 1'b0;
if (i_rst) begin
if (reset_strategy != "NONE")
wcnt <= 5'd0;
end
end
/*
********** Read side ***********
*/
reg [4:0] rcnt;
wire rtrig0;
reg rtrig1;
wire [$clog2(32+csr_regs)-1:0] rreg = rtrig0 ? i_rreg1 : i_rreg0;
generate if (width == 32)
assign o_raddr = rreg;
else
assign o_raddr = {rreg, rcnt[4:l2w]};
endgenerate
reg [width-1:0] rdata0;
reg [width-2:0] rdata1;
assign o_rdata0 = rdata0[0];
assign o_rdata1 = rtrig1 ? i_rdata[0] : rdata1[0];
assign rtrig0 = (rcnt[l2w-1:0] == 1);
reg rreq_r;
generate if (width>2)
always @(posedge i_clk) begin
rdata1 <= {1'b0,rdata1[width-2:1]}; //Optimize?
if (rtrig1)
rdata1[width-2:0] <= i_rdata[width-1:1];
end
else
always @(posedge i_clk) if (rtrig1) rdata1 <= i_rdata[1];
endgenerate
always @(posedge i_clk) begin
rtrig1 <= rtrig0;
rcnt <= rcnt+5'd1;
if (i_rreq)
rcnt <= 5'd0;
rreq_r <= i_rreq;
rgnt <= rreq_r;
rdata0 <= {1'b0,rdata0[width-1:1]};
if (rtrig0)
rdata0 <= i_rdata;
if (i_rst) begin
if (reset_strategy != "NONE") begin
rgnt <= 1'b0;
rreq_r <= 1'b0;
end
end
end
endmodule