`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