aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/control/ram_2port_impl.vh
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/control/ram_2port_impl.vh')
-rw-r--r--fpga/usrp3/lib/control/ram_2port_impl.vh129
1 files changed, 129 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/ram_2port_impl.vh b/fpga/usrp3/lib/control/ram_2port_impl.vh
new file mode 100644
index 000000000..8f8f3bab3
--- /dev/null
+++ b/fpga/usrp3/lib/control/ram_2port_impl.vh
@@ -0,0 +1,129 @@
+//
+// Copyright 2011 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Used by ram_2port.v
+// Requires `RAM_MOD_NAME and `RAM_DIRECTIVE to be defined
+
+module `RAM_MOD_NAME #(
+ parameter DWIDTH = 32, // Width of the memory block
+ parameter AWIDTH = 9, // log2 of the depth of the memory block
+ parameter RW_MODE = "READ-FIRST", // Read-write mode {READ-FIRST, WRITE-FIRST, NO-CHANGE}
+ parameter OUT_REG = 0, // Instantiate an output register? (+1 cycle of read latency)
+ parameter INIT_FILE = "" // Optionally initialize memory with this file
+) (
+ input wire clka,
+ input wire ena,
+ input wire wea,
+ input wire [AWIDTH-1:0] addra,
+ input wire [DWIDTH-1:0] dia,
+ output wire [DWIDTH-1:0] doa,
+
+ input wire clkb,
+ input wire enb,
+ input wire web,
+ input wire [AWIDTH-1:0] addrb,
+ input wire [DWIDTH-1:0] dib,
+ output wire [DWIDTH-1:0] dob
+);
+
+ `RAM_DIRECTIVE reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
+
+ // Initialize ram to a specified file or to all zeros to match hardware
+ generate if (INIT_FILE != "") begin
+ initial
+ $readmemh(INIT_FILE, ram, 0, (1<<AWIDTH)-1);
+ end else begin
+ integer i;
+ initial
+ for (i = 0; i < (1<<AWIDTH); i = i + 1)
+ ram[i] = {DWIDTH{1'b0}};
+ end endgenerate
+
+ reg [DWIDTH-1:0] doa_r = 'h0, dob_r = 'h0;
+ generate if (OUT_REG == 1) begin
+ // A 2 clock cycle read latency with improve clock-to-out timing
+ reg [DWIDTH-1:0] doa_rr = 'h0, dob_rr = 'h0;
+
+ always @(posedge clka)
+ if (ena)
+ doa_rr <= doa_r;
+
+ always @(posedge clkb)
+ if (enb)
+ dob_rr <= dob_r;
+
+ assign doa = doa_rr;
+ assign dob = dob_rr;
+ end else begin
+ // A 1 clock cycle read latency at the cost of a longer clock-to-out timing
+ assign doa = doa_r;
+ assign dob = dob_r;
+ end endgenerate
+
+ generate if (RW_MODE == "READ-FIRST") begin
+ // When data is written, the prior memory contents at the write
+ // address are presented on the output port.
+ always @(posedge clka) begin
+ if (ena) begin
+ if (wea)
+ ram[addra] <= dia;
+ doa_r <= ram[addra];
+ end
+ end
+ always @(posedge clkb) begin
+ if (enb) begin
+ if (web)
+ ram[addrb] <= dib;
+ dob_r <= ram[addrb];
+ end
+ end
+
+ end else if (RW_MODE == "WRITE-FIRST") begin
+ // The data being written to the RAM also resides on the output port.
+ always @(posedge clka) begin
+ if (ena) begin
+ if (wea) begin
+ ram[addra] <= dia;
+ doa_r <= dia;
+ end else begin
+ doa_r <= ram[addra];
+ end
+ end
+ end
+ always @(posedge clkb) begin
+ if (enb) begin
+ if (web) begin
+ ram[addrb] <= dib;
+ dob_r <= dib;
+ end else begin
+ dob_r <= ram[addrb];
+ end
+ end
+ end
+
+ end else begin
+ // This is a no change RAM which retains the last read value on the output during writes
+ // which is the most power efficient mode.
+ always @(posedge clka) begin
+ if (ena) begin
+ if (wea)
+ ram[addra] <= dia;
+ else
+ doa_r <= ram[addra];
+ end
+ end
+ always @(posedge clkb) begin
+ if (enb) begin
+ if (web)
+ ram[addrb] <= dib;
+ else
+ dob_r <= ram[addrb];
+ end
+ end
+
+ end endgenerate
+
+endmodule