Compare commits

...

3 Commits

Author SHA1 Message Date
David Anderson a69cc878ce experiments/primitive_ram: customize the clock/reset of one of the RAM ports 2024-08-17 16:41:24 -07:00
David Anderson a23661a449 lib: default clocks and resets to the ambient ones from context
Callers can still specify whacky cross-domain RAMs in the cfg, but the
default is what you usually want: a dual-port RAM with both ports in the
caller's clock/reset domain.
2024-08-17 16:39:45 -07:00
David Anderson e64b990f80 lib: fix port B reset wiring for ECP5_RAM 2024-08-17 16:38:52 -07:00
3 changed files with 45 additions and 15 deletions

View File

@ -2,13 +2,19 @@ package Top;
import ECP5_RAM::*; import ECP5_RAM::*;
(* synthesize *) (* always_enabled *)
module mkTop(ECP5_EBRCorePort#(Bit#(12), Bit#(8))); interface Top;
let clk <- exposeCurrentClock; method Action put(UInt#(3) select, Bool write, Bit#(12) address, Bit#(4) data);
let rstN <- exposeCurrentReset; method Bit#(4) read();
endinterface
ECP5_EBRPortConfig cfg = defaultValue; (* synthesize *)
ECP5_EBRCore#(Bit#(12), Bit#(8), UInt#(12), UInt#(8)) ram <- mkECP5_EBRCoreByte(cfg, cfg); module mkTop(Clock extClk, Reset extRst, Top ifc);
ECP5_EBRPortConfig cfgA = defaultValue;
cfgA.clk = tagged Valid extClk;
cfgA.rstN = tagged Valid extRst;
ECP5_EBRPortConfig cfgB = defaultValue;
ECP5_EBRCore#(Bit#(12), Bit#(4), UInt#(12), UInt#(4)) ram <- mkECP5_EBRCore(cfgA, cfgB);
method put = ram.portA.put; method put = ram.portA.put;
method read = ram.portA.read; method read = ram.portA.read;

View File

@ -17,8 +17,12 @@ typedef enum {
// ECP5_EBRPortConfig is the static configuration of an EBR port. // ECP5_EBRPortConfig is the static configuration of an EBR port.
typedef struct { typedef struct {
Clock clk; // clk, if specified, is the Clock to use for the port. If
Reset rstN; // unspecified, uses the module default clock.
Maybe#(Clock) clk;
// rstN, if specified, is the Reset to use for the port. If
// unspecified, uses the module default reset.
Maybe#(Reset) rstN;
// By default, ECP5 EBRs only register the input address and write // By default, ECP5 EBRs only register the input address and write
// data, giving a 1-cycle latency for operations. If // data, giving a 1-cycle latency for operations. If
// registered_output is true, the output value is also registered, // registered_output is true, the output value is also registered,
@ -34,8 +38,8 @@ typedef struct {
instance DefaultValue#(ECP5_EBRPortConfig); instance DefaultValue#(ECP5_EBRPortConfig);
defaultValue = ECP5_EBRPortConfig{ defaultValue = ECP5_EBRPortConfig{
clk: noClock, clk: defaultValue,
rstN: noReset, rstN: defaultValue,
registered_output: False, registered_output: False,
chip_select_addr: 0, chip_select_addr: 0,
write_mode: Normal write_mode: Normal
@ -68,14 +72,34 @@ import "BVI" ECP5_RAM =
Integer portB_width) Integer portB_width)
(ECP5_EBRCoreInner); (ECP5_EBRCoreInner);
let defClk <- exposeCurrentClock;
let defRstN <- exposeCurrentReset;
let portA_bsv_clock = case (port_a.clk) matches
tagged Invalid: defClk;
tagged Valid .clk: clk;
endcase;
let portA_bsv_rstN = case (port_a.rstN) matches
tagged Invalid: defRstN;
tagged Valid .rstN: rstN;
endcase;
let portB_bsv_clock = case (port_b.clk) matches
tagged Invalid: defClk;
tagged Valid .clk: clk;
endcase;
let portB_bsv_rstN = case (port_b.rstN) matches
tagged Invalid: defRstN;
tagged Valid .rstN: rstN;
endcase;
default_clock no_clock; default_clock no_clock;
default_reset no_reset; default_reset no_reset;
input_clock portA_clk(CLKA, (* unused *)CLKA_GATE) = port_a.clk; input_clock portA_clk(CLKA, (* unused *)CLKA_GATE) = portA_bsv_clock;
input_reset portA_rstN(RSTA) clocked_by(portA_clk) = port_a.rstN; input_reset portA_rstN(RSTA) clocked_by(portA_clk) = portA_bsv_rstN;
input_clock portB_clk(CLKB, (* unused *)CLKB_GATE) = port_b.clk; input_clock portB_clk(CLKB, (* unused *)CLKB_GATE) = portB_bsv_clock;
input_reset portB_rstN(RSTB) clocked_by(portB_clk) = port_b.rstN; input_reset portB_rstN(RSTB) clocked_by(portB_clk) = portB_bsv_rstN;
parameter DATA_WIDTH_A = portA_width; parameter DATA_WIDTH_A = portA_width;
parameter REGMODE_A = port_a.registered_output ? "OUTREG" : "NOREG"; parameter REGMODE_A = port_a.registered_output ? "OUTREG" : "NOREG";

View File

@ -160,7 +160,7 @@ module ECP5_RAM(CLKA,
.CSA2(CSA[2]), .CSA2(CSA[2]),
.CSA1(CSA[1]), .CSA1(CSA[1]),
.CSA0(CSA[0]), .CSA0(CSA[0]),
.RSTB(RSTA), .RSTB(RSTB),
.DOB17(DOB[17]), .DOB17(DOB[17]),
.DOB16(DOB[16]), .DOB16(DOB[16]),
.DOB15(DOB[15]), .DOB15(DOB[15]),