mirror of
https://github.com/olofk/serv.git
synced 2025-04-21 12:27:08 -04:00
150 lines
3.3 KiB
Verilog
150 lines
3.3 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;
|
|
reg [4:0] rcnt;
|
|
|
|
/*
|
|
********** Write side ***********
|
|
*/
|
|
|
|
wire [4:0] wcnt;
|
|
|
|
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 = (wtrig0 & wen0_r) | (wtrig1 & wen1_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
|
|
|
|
assign wcnt = rcnt-3;
|
|
|
|
always @(posedge i_clk) begin
|
|
wen0_r <= i_wen0;
|
|
wen1_r <= i_wen1;
|
|
|
|
wdata1_r <= {i_wdata1,wdata1_r[width-1:1]};
|
|
|
|
end
|
|
|
|
/*
|
|
********** Read side ***********
|
|
*/
|
|
|
|
|
|
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;
|
|
if (i_wreq)
|
|
rcnt <= 5'd2;
|
|
|
|
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
|