mirror of
https://github.com/olofk/serv.git
synced 2026-02-25 07:49:57 +00:00
Rewrite serv_rf_ram_if
This adds some optimizations to serv_rf_ram_if. It also adds a read enable signal and delays writes one cycle which has the added bonus that no reads or writes happen in the same cycle for RF_WIDTH > 2. This allows SERV to be used with single-port RAMs in most cases.
This commit is contained in:
@@ -7,6 +7,7 @@ module serv_rf_ram
|
||||
input wire [width-1:0] i_wdata,
|
||||
input wire i_wen,
|
||||
input wire [$clog2(depth)-1:0] i_raddr,
|
||||
input wire i_ren,
|
||||
output wire [width-1:0] o_rdata);
|
||||
|
||||
reg [width-1:0] memory [0:depth-1];
|
||||
@@ -15,7 +16,7 @@ module serv_rf_ram
|
||||
always @(posedge i_clk) begin
|
||||
if (i_wen)
|
||||
memory[i_waddr] <= i_wdata;
|
||||
rdata <= memory[i_raddr];
|
||||
rdata <= i_ren ? memory[i_raddr] : {width{1'bx}};
|
||||
end
|
||||
|
||||
/* Reads from reg x0 needs to return 0
|
||||
|
||||
@@ -1,68 +1,81 @@
|
||||
`default_nettype none
|
||||
module serv_rf_ram_if
|
||||
#(parameter width=8,
|
||||
#(//Data width. Adjust to preferred width of SRAM data interface
|
||||
parameter width=8,
|
||||
|
||||
//Select reset strategy.
|
||||
// "MINI" for resetting minimally required FFs
|
||||
// "NONE" for relying on FFs having a defined value on startup
|
||||
parameter reset_strategy="MINI",
|
||||
|
||||
//Number of CSR registers. These are allocated after the normal
|
||||
// GPR registers in the RAM.
|
||||
parameter csr_regs=4,
|
||||
parameter depth=32*(32+csr_regs)/width,
|
||||
parameter l2w = $clog2(width))
|
||||
|
||||
//Internal parameters calculated from above values. Do not change
|
||||
parameter raw=$clog2(32+csr_regs), //Register address width
|
||||
parameter l2w=$clog2(width), //log2 of width
|
||||
parameter aw=5+raw-l2w) //Address 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,
|
||||
input wire i_clk,
|
||||
input wire i_rst,
|
||||
input wire i_wreq,
|
||||
input wire i_rreq,
|
||||
output wire o_ready,
|
||||
input wire [raw-1:0] i_wreg0,
|
||||
input wire [raw-1:0] i_wreg1,
|
||||
input wire i_wen0,
|
||||
input wire i_wen1,
|
||||
input wire i_wdata0,
|
||||
input wire i_wdata1,
|
||||
input wire [raw-1:0] i_rreg0,
|
||||
input wire [raw-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);
|
||||
output wire [aw-1:0] o_waddr,
|
||||
output wire [width-1:0] o_wdata,
|
||||
output wire o_wen,
|
||||
output wire [aw-1:0] o_raddr,
|
||||
output wire o_ren,
|
||||
input wire [width-1:0] i_rdata);
|
||||
|
||||
reg rgnt;
|
||||
assign o_ready = rgnt | i_wreq;
|
||||
reg [4:0] rcnt;
|
||||
|
||||
reg rtrig1;
|
||||
/*
|
||||
********** Write side ***********
|
||||
*/
|
||||
|
||||
wire [4:0] wcnt;
|
||||
|
||||
reg [width-2:0] wdata0_r;
|
||||
reg [width-1:0] wdata1_r;
|
||||
reg [width-1:0] wdata0_r;
|
||||
reg [width-0:0] wdata1_r;
|
||||
|
||||
reg wen0_r;
|
||||
reg wen1_r;
|
||||
wire wtrig0;
|
||||
wire wtrig1;
|
||||
|
||||
assign wtrig0 = rtrig1;
|
||||
|
||||
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};
|
||||
wdata1_r[width-1:0] :
|
||||
wdata0_r;
|
||||
|
||||
wire [$clog2(32+csr_regs)-1:0] wreg = wtrig1 ? i_wreg1 : i_wreg0;
|
||||
wire [raw-1:0] wreg = wtrig1 ? i_wreg1 : i_wreg0;
|
||||
generate if (width == 32)
|
||||
assign o_waddr = wreg;
|
||||
else
|
||||
@@ -71,19 +84,16 @@ module serv_rf_ram_if
|
||||
|
||||
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;
|
||||
assign wcnt = rcnt-4;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
wen0_r <= i_wen0;
|
||||
wen1_r <= i_wen1;
|
||||
if (wcnt[0]) begin
|
||||
wen0_r <= i_wen0;
|
||||
wen1_r <= i_wen1;
|
||||
end
|
||||
|
||||
wdata1_r <= {i_wdata1,wdata1_r[width-1:1]};
|
||||
wdata0_r <= {i_wdata0,wdata0_r[width-1:1]};
|
||||
wdata1_r <= {i_wdata1,wdata1_r[width-0:1]};
|
||||
|
||||
end
|
||||
|
||||
@@ -93,9 +103,8 @@ module serv_rf_ram_if
|
||||
|
||||
|
||||
wire rtrig0;
|
||||
reg rtrig1;
|
||||
|
||||
wire [$clog2(32+csr_regs)-1:0] rreg = rtrig0 ? i_rreg1 : i_rreg0;
|
||||
wire [raw-1:0] rreg = rtrig0 ? i_rreg1 : i_rreg0;
|
||||
generate if (width == 32)
|
||||
assign o_raddr = rreg;
|
||||
else
|
||||
@@ -105,11 +114,19 @@ module serv_rf_ram_if
|
||||
reg [width-1:0] rdata0;
|
||||
reg [width-2:0] rdata1;
|
||||
|
||||
reg rgate;
|
||||
|
||||
assign o_rdata0 = rdata0[0];
|
||||
assign o_rdata1 = rtrig1 ? i_rdata[0] : rdata1[0];
|
||||
|
||||
assign rtrig0 = (rcnt[l2w-1:0] == 1);
|
||||
|
||||
generate if (width == 2)
|
||||
assign o_ren = rgate;
|
||||
else
|
||||
assign o_ren = rgate & (rcnt[l2w-1:1] == 0);
|
||||
endgenerate
|
||||
|
||||
reg rreq_r;
|
||||
|
||||
generate if (width>2)
|
||||
@@ -123,12 +140,13 @@ module serv_rf_ram_if
|
||||
endgenerate
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (&rcnt | i_rreq)
|
||||
rgate <= i_rreq;
|
||||
|
||||
rtrig1 <= rtrig0;
|
||||
rcnt <= rcnt+5'd1;
|
||||
if (i_rreq)
|
||||
rcnt <= 5'd0;
|
||||
if (i_wreq)
|
||||
rcnt <= 5'd2;
|
||||
if (i_rreq | i_wreq)
|
||||
rcnt <= {3'd0,i_wreq,1'b0};
|
||||
|
||||
rreq_r <= i_rreq;
|
||||
rgnt <= rreq_r;
|
||||
@@ -139,8 +157,10 @@ module serv_rf_ram_if
|
||||
|
||||
if (i_rst) begin
|
||||
if (reset_strategy != "NONE") begin
|
||||
rgate <= 1'b0;
|
||||
rgnt <= 1'b0;
|
||||
rreq_r <= 1'b0;
|
||||
rcnt <= 5'd0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -98,6 +98,7 @@ module serv_rf_top
|
||||
wire [RF_WIDTH-1:0] wdata;
|
||||
wire wen;
|
||||
wire [RF_L2D-1:0] raddr;
|
||||
wire ren;
|
||||
wire [RF_WIDTH-1:0] rdata;
|
||||
|
||||
serv_rf_ram_if
|
||||
@@ -124,6 +125,7 @@ module serv_rf_top
|
||||
.o_wdata (wdata),
|
||||
.o_wen (wen),
|
||||
.o_raddr (raddr),
|
||||
.o_ren (ren),
|
||||
.i_rdata (rdata));
|
||||
|
||||
serv_rf_ram
|
||||
@@ -135,6 +137,7 @@ module serv_rf_top
|
||||
.i_wdata (wdata),
|
||||
.i_wen (wen),
|
||||
.i_raddr (raddr),
|
||||
.i_ren (ren),
|
||||
.o_rdata (rdata));
|
||||
|
||||
serv_top
|
||||
|
||||
Reference in New Issue
Block a user