From b9671b1ba991b7e9aa3c711925b7dc8362432407 Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Mon, 13 Oct 2025 15:18:02 -0400 Subject: [PATCH 1/4] Set up tdpram --- lambdalib/ramlib/la_tdpram/la_tdpram.py | 12 +++ lambdalib/ramlib/la_tdpram/rtl/la_tdpram.v | 85 +++++++++++++++++ .../ramlib/la_tdpram/rtl/la_tdpram_impl.v | 95 +++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 lambdalib/ramlib/la_tdpram/la_tdpram.py create mode 100644 lambdalib/ramlib/la_tdpram/rtl/la_tdpram.v create mode 100644 lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v diff --git a/lambdalib/ramlib/la_tdpram/la_tdpram.py b/lambdalib/ramlib/la_tdpram/la_tdpram.py new file mode 100644 index 00000000..d58e2d7f --- /dev/null +++ b/lambdalib/ramlib/la_tdpram/la_tdpram.py @@ -0,0 +1,12 @@ +from lambdalib.lambdalib import Lambda + + +class Tdpram(Lambda): + def __init__(self): + name = 'la_tdpram' + super().__init__(name, __file__, extrasources=['rtl/la_tdpram_impl.v']) + + +if __name__ == "__main__": + d = Tdpram() + d.write_fileset(f"{d.name}.f", fileset="rtl") diff --git a/lambdalib/ramlib/la_tdpram/rtl/la_tdpram.v b/lambdalib/ramlib/la_tdpram/rtl/la_tdpram.v new file mode 100644 index 00000000..64fc4050 --- /dev/null +++ b/lambdalib/ramlib/la_tdpram/rtl/la_tdpram.v @@ -0,0 +1,85 @@ +/***************************************************************************** + * Function: + * Copyright: Lambda Project Authors. All rights Reserved. + * License: MIT (see LICENSE file in Lambda repository) + * + * Docs: + * + * This is a wrapper for selecting from a set of hardened memory macros. + * + * A synthesizable reference model is used when the PROP is DEFAULT. The + * synthesizable model does not implement the cfg and test interface and should + * only be used for basic testing and for synthesizing for FPGA devices. + * Advanced ASIC development should rely on complete functional models + * supplied on a per macro basis. + * + * Technology specific implementations of "la_tdpram" would generally include + * one or more hardcoded instantiations of RAM modules with a generate + * statement relying on the "PROP" to select between the list of modules + * at build time. + * + ****************************************************************************/ + +module la_tdpram #( + parameter DW = 32, // Memory width + parameter AW = 10, // address width (derived) + parameter PROP = "DEFAULT", // pass through variable for hard macro + parameter CTRLW = 128, // width of asic ctrl interface + parameter TESTW = 128 // width of asic test interface +) ( // A port + input clk_a, // write clock + input ce_a, // write chip-enable + input we_a, // write enable + input [DW-1:0] wmask_a, // write mask + input [AW-1:0] addr_a, // write address + input [DW-1:0] din_a, // write data in + output [DW-1:0] dout_a, // read data out + // B port + input clk_b, // write clock + input ce_b, // write chip-enable + input we_b, // write enable + input [DW-1:0] wmask_b, // write mask + input [AW-1:0] addr_b, // write address + input [DW-1:0] din_b, // write data in + output [DW-1:0] dout_b, // read data out + // Power signal + input vss, // ground signal + input vdd, // memory core array power + input vddio, // periphery/io power + // Generic interfaces + input [CTRLW-1:0] ctrl, // pass through ASIC control interface + input [TESTW-1:0] test // pass through ASIC test interface +); + + la_tdpram_impl #( + .DW (DW), + .AW (AW), + .PROP (PROP), + .CTRLW (CTRLW), + .TESTW (TESTW) + ) memory ( + .clk_a (clk_a), + .ce_a (ce_a), + .we_a (we_a), + .wmask_a (wmask_a), + .addr_a (addr_a), + .din_a (din_a), + .dout_a (dout_a), + + .clk_b (clk_b), + .ce_b (ce_b), + .we_b (we_b), + .wmask_b (wmask_b), + .addr_b (addr_b), + .din_b (din_b), + .dout_b (dout_b), + + .vss (vss), + .vdd (vdd), + .vddio (vddio), + + .ctrl (ctrl), + .test (test) + ); + +endmodule diff --git a/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v b/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v new file mode 100644 index 00000000..791fd6d4 --- /dev/null +++ b/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v @@ -0,0 +1,95 @@ +/***************************************************************************** + * Function: True Dual Port RAM (Two write + read ports) + * Copyright: Lambda Project Authors. All rights Reserved. + * License: MIT (see LICENSE file in Lambda repository) + * + * Docs: + * + * This is a wrapper for selecting from a set of hardened memory macros. + * + * A synthesizable reference model is used when the PROP is DEFAULT. The + * synthesizable model does not implement the cfg and test interface and should + * only be used for basic testing and for synthesizing for FPGA devices. + * Advanced ASIC development should rely on complete functional models + * supplied on a per macro basis. + * + * Technology specific implementations of "la_tdpram" would generally include + * one or more hardcoded instantiations of RAM modules with a generate + * statement relying on the "PROP" to select between the list of modules + * at build time. + * + ****************************************************************************/ + +module la_tdpram_impl #( + parameter DW = 32, // Memory width + parameter AW = 10, // address width (derived) + parameter PROP = "DEFAULT", // pass through variable for hard macro + parameter CTRLW = 128, // width of asic ctrl interface + parameter TESTW = 128 // width of asic test interface +) ( // Write port + input clk_a, // write clock + input ce_a, // write chip-enable + input we_a, // write enable + input [DW-1:0] wmask_a, // write mask + input [AW-1:0] addr_a, // write address + input [DW-1:0] din_a, // write data in + output reg [DW-1:0] dout_a, // read data out + // B port + input clk_b, // write clock + input ce_b, // write chip-enable + input we_b, // write enable + input [DW-1:0] wmask_b, // write mask + input [AW-1:0] addr_b, // write address + input [DW-1:0] din_b, // write data in + output reg [DW-1:0] dout_b, // read data out + // Power signal + input vss, // ground signal + input vdd, // memory core array power + input vddio, // periphery/io power + // Generic interfaces + input [CTRLW-1:0] ctrl, // pass through ASIC control interface + input [TESTW-1:0] test // pass through ASIC test interface +); + + // Generic RTL RAM + /* verilator lint_off MULTIDRIVEN */ + reg [DW-1:0] ram[(2**AW)-1:0]; + /* verilator lint_on MULTIDRIVEN */ + + genvar i; + + /* verilator lint_off MULTIDRIVEN */ + generate + for (i = 0; i < DW; i = i + 1) begin + // Port A write + always @(posedge clk_a) begin + if (ce_a && we_a && wmask_a[i]) begin + ram[addr_a][i] <= din_a[i]; + end + end + // Port B write + always @(posedge clk_b) begin + if (ce_b && we_b && wmask_b[i]) begin + ram[addr_b][i] <= din_b[i]; + end + end + + end + endgenerate + /* verilator lint_on MULTIDRIVEN */ + + // Port A read + always @(posedge clk_a) begin + if (ce_a && ~we_a) begin + dout_a <= ram[addr_a]; + end + end + + // Port B read + always @(posedge clk_b) begin + if (ce_b && ~we_b) begin + dout_b <= ram[addr_b]; + end + end + +endmodule From 30d03c9ef39b2b219bf589f588de4d61ef254a67 Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Mon, 13 Oct 2025 16:14:42 -0400 Subject: [PATCH 2/4] Update ramlib init --- lambdalib/ramlib/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lambdalib/ramlib/__init__.py b/lambdalib/ramlib/__init__.py index 8e27decf..2bc9ba65 100644 --- a/lambdalib/ramlib/__init__.py +++ b/lambdalib/ramlib/__init__.py @@ -4,11 +4,13 @@ from .la_syncfifo.la_syncfifo import Syncfifo from .la_dpram.la_dpram import Dpram from .la_spram.la_spram import Spram +from .la_spram.la_spram import Tdpram __all__ = ['Asyncfifo', 'Syncfifo', 'Dpram', - 'Spram'] + 'Spram', + 'Tdpram'] class RAMLib(Design): @@ -20,3 +22,4 @@ def __init__(self): self.add_depfileset(Syncfifo(), depfileset="rtl") self.add_depfileset(Dpram(), depfileset="rtl") self.add_depfileset(Spram(), depfileset="rtl") + self.add_depfileset(Tdpram(), depfileset="rtl") From d7f904585ebb4210636d0331ac97d843160f8b2f Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Mon, 13 Oct 2025 16:20:48 -0400 Subject: [PATCH 3/4] Fix naming errors --- lambdalib/ramlib/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambdalib/ramlib/__init__.py b/lambdalib/ramlib/__init__.py index 2bc9ba65..80e5dfe8 100644 --- a/lambdalib/ramlib/__init__.py +++ b/lambdalib/ramlib/__init__.py @@ -4,7 +4,7 @@ from .la_syncfifo.la_syncfifo import Syncfifo from .la_dpram.la_dpram import Dpram from .la_spram.la_spram import Spram -from .la_spram.la_spram import Tdpram +from .la_tdpram.la_tdpram import Tdpram __all__ = ['Asyncfifo', 'Syncfifo', From 24cd4de3a164c856a35f82fe445320964d3b6f23 Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Thu, 23 Oct 2025 15:29:42 -0400 Subject: [PATCH 4/4] Fix looping style --- .../ramlib/la_tdpram/rtl/la_tdpram_impl.v | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v b/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v index 791fd6d4..4a345508 100644 --- a/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v +++ b/lambdalib/ramlib/la_tdpram/rtl/la_tdpram_impl.v @@ -56,27 +56,25 @@ module la_tdpram_impl #( reg [DW-1:0] ram[(2**AW)-1:0]; /* verilator lint_on MULTIDRIVEN */ - genvar i; + integer i; - /* verilator lint_off MULTIDRIVEN */ - generate + // Port A write + always @(posedge clk_a) begin for (i = 0; i < DW; i = i + 1) begin - // Port A write - always @(posedge clk_a) begin - if (ce_a && we_a && wmask_a[i]) begin - ram[addr_a][i] <= din_a[i]; - end - end - // Port B write - always @(posedge clk_b) begin - if (ce_b && we_b && wmask_b[i]) begin - ram[addr_b][i] <= din_b[i]; - end + if (ce_a && we_a && wmask_a[i]) begin + ram[addr_a][i] <= din_a[i]; end + end + end + // Port B write + always @(posedge clk_b) begin + for (i = 0; i < DW; i = i + 1) begin + if (ce_b && we_b && wmask_b[i]) begin + ram[addr_b][i] <= din_b[i]; + end end - endgenerate - /* verilator lint_on MULTIDRIVEN */ + end // Port A read always @(posedge clk_a) begin