aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/intel_alm/common/mem_sim.v
diff options
context:
space:
mode:
authorDan Ravensloft <dan.ravensloft@gmail.com>2020-04-16 12:24:04 +0100
committerMarcelina Koƛcielnicka <mwk@0x04.net>2020-05-07 21:03:13 +0200
commit5b779f7f4ef0bf2c4ad3a412da24fad30b078626 (patch)
treecb0fcd56575efe8a846fbd6a2888aee80998f644 /techlibs/intel_alm/common/mem_sim.v
parent06104249406972de01d0360df63a32cafcdf2ec5 (diff)
downloadyosys-5b779f7f4ef0bf2c4ad3a412da24fad30b078626.tar.gz
yosys-5b779f7f4ef0bf2c4ad3a412da24fad30b078626.tar.bz2
yosys-5b779f7f4ef0bf2c4ad3a412da24fad30b078626.zip
intel_alm: direct LUTRAM cell instantiation
By instantiating the LUTRAM cell directly, we avoid a trip through altsyncram, which speeds up Quartus synthesis time. This also gives a little more flexibility, as Yosys can build RAMs out of individual 32x1 LUTRAM cells. While working on this, I discovered that the mem_init0 parameter of <family>_mlab_cell gets ignored by Quartus.
Diffstat (limited to 'techlibs/intel_alm/common/mem_sim.v')
-rw-r--r--techlibs/intel_alm/common/mem_sim.v60
1 files changed, 60 insertions, 0 deletions
diff --git a/techlibs/intel_alm/common/mem_sim.v b/techlibs/intel_alm/common/mem_sim.v
new file mode 100644
index 000000000..ae79b19a4
--- /dev/null
+++ b/techlibs/intel_alm/common/mem_sim.v
@@ -0,0 +1,60 @@
+// The MLAB
+// --------
+// In addition to Logic Array Blocks (LABs) that contain ten Adaptive Logic
+// Modules (ALMs, see alm_sim.v), the Cyclone V/10GX also contain
+// Memory/Logic Array Blocks (MLABs) that can act as either ten ALMs, or utilise
+// the memory the ALM uses to store the look-up table data for general usage,
+// producing a 32 address by 20-bit block of memory. MLABs are spread out
+// around the chip, so they can be placed near where they are needed, rather than
+// being comparatively limited in placement for a deep but narrow memory such as
+// the M10K memory block.
+//
+// MLABs are used mainly for shallow but wide memories, such as CPU register
+// files (which have perhaps 32 registers that are comparatively wide (16/32-bit))
+// or shift registers (by using the output of the Nth bit as input for the N+1th
+// bit).
+//
+// Oddly, instead of providing a block 32 address by 20-bit cell, Quartus asks
+// synthesis tools to build MLABs out of 32 address by 1-bit cells, and tries
+// to put these cells in the same MLAB during cell placement. Because of this
+// a MISTRAL_MLAB cell represents one of these 32 address by 1-bit cells, and
+// 20 of them represent a physical MLAB.
+//
+// How the MLAB works
+// ------------------
+// MLABs are poorly documented, so the following information is based mainly
+// on the simulation model and my knowledge of how memories like these work.
+// Additionally, note that the ports of MISTRAL_MLAB are the ones auto-generated
+// by the Yosys `memory_bram` pass, and it doesn't make sense to me to use
+// `techmap` just for the sake of renaming the cell ports.
+//
+// The MLAB can be initialised to any value, but unfortunately Quartus only
+// allows memory initialisation from a file. Since Yosys doesn't preserve input
+// file information, or write the contents of an `initial` block to a file,
+// Yosys can't currently initialise the MLAB in a way Quartus will accept.
+//
+// The MLAB takes in data from A1DATA at the rising edge of CLK1, and if A1EN
+// is high, writes it to the address in A1ADDR. A1EN can therefore be used to
+// conditionally write data to the MLAB.
+//
+// Simultaneously, the MLAB reads data from B1ADDR, and outputs it to B1DATA,
+// asynchronous to CLK1 and ignoring A1EN. If a synchronous read is needed
+// then the output can be fed to embedded flops. Presently, Yosys assumes
+// Quartus will pack external flops into the MLAB, but this is an assumption
+// that needs testing.
+
+// The vendor sim model outputs 'x for a very short period (a few
+// combinational delta cycles) after each write. This has been omitted from
+// the following model because it's very difficult to trigger this in practice
+// as clock cycles will be much longer than any potential blip of 'x, so the
+// model can be treated as always returning a defined result.
+module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA);
+
+reg [31:0] mem = 32'b0;
+
+always @(posedge CLK1)
+ if (A1EN) mem[A1ADDR] <= A1DATA;
+
+assign B1DATA = mem[B1ADDR];
+
+endmodule