Storage infers from a clocked process. Reset comes first, then the enable guard, so reset wins regardless of enable.
// yosys: ok
module dff_en (
input logic clk, rst_n, en,
input logic [7:0] d,
output logic [7:0] q
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) q <= '0;
else if (en) q <= d;
end
endmoduleThe middle row, en, decides whether d reaches q. Inputs change just after a rising edge, so the values drawn in one slot are captured at the edge that starts the next slot: q trails d by one cycle.
Slot 1: rst_n is 0, so q is 0 (in reset).
Slot 2: rst_n is 1, en is 1 and d is a5. q is still 0; nothing has been captured yet.
Slot 3: the edge captured a5, so q is a5. Now en is 0 and d is 3c.
Slot 4: en was 0 at the edge, so q holds a5. en goes back to 1.
Slot 5: the edge captured 3c, so q is 3c. d changes to f0.
Slot 6: the edge captured f0, so q is f0.
Slot 7: rst_n falls, so q is 0 at once (the asynchronous reset does not wait for an edge).
This array has clocked writes and registered reads with read-first RTL semantics. It is compatible with some synchronous RAM templates, subject to target dimensions, ports and collision support. Mapping reports must confirm the actual resource. This version reads the old word when one address is written and read together.
// yosys: ok
module ram_sp_sync #(parameter int AW = 4, parameter int DW = 8) (
input logic clk, wr_en,
input logic [AW-1:0] addr,
input logic [DW-1:0] wdata,
output logic [DW-1:0] rdata
);
logic [DW-1:0] mem [2**AW]; // no reset on the array, so it can map to a block RAM
always_ff @(posedge clk) begin
if (wr_en) mem[addr] <= wdata; // synchronous write
rdata <= mem[addr]; // synchronous read: old word on a same-address collision
end
endmoduleWaveform modeling assumption: its separate source zero-fills memory initially, hence 00 on the first writes to addresses 3 and 5. The lesson RAM above has no initialization: an unwritten old word is unknown in four-state simulation, not guaranteed zero in hardware. The bench below preloads addresses before checking their data and collision behavior.
The bottom row, rdata, trails the address by one cycle: the access drawn in one slot completes at the edge that starts the next slot.
Slot 1: write 22 to address 3. rdata is 00 from the read of address 3 one cycle earlier.
Slot 2: read address 3. rdata is 00: the slot 1 write and read hit address 3 together, so the read returned the old word.
Slot 3: write 11 to address 3. rdata is 22 from the slot 2 read.
Slot 4: read address 3. rdata is still 22: the slot 3 write collided and returned the old word (read-first).
Slot 5: write 77 to address 5. rdata is 11 from the slot 4 read.
Slot 6: read address 5. rdata is 00, the old word under the slot 5 write.
Slot 7: rdata is 77 from the slot 6 read.
The collision policy is explicit: a same-cycle write plus read returns the old word. The new word is visible in a read issued in a later cycle.
d changes. What does q do?Nothing. It holds its value until enable is high at a clock edge.
The old word. The new data is visible in a read issued in a later cycle, as slots 3 to 5 of the waveform show: the slot 3 write returns 22 in slot 4, and the slot 4 read returns 11 in slot 5.
The flop and the RAM plus a testbench that checks reset, enable and the collision.
module dff_en (
input logic clk, rst_n, en,
input logic [7:0] d,
output logic [7:0] q
);
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) q <= '0;
else if (en) q <= d;
end
endmodule
module ram_sp_sync #(parameter int AW = 4, parameter int DW = 8) (
input logic clk, wr_en,
input logic [AW-1:0] addr,
input logic [DW-1:0] wdata,
output logic [DW-1:0] rdata
);
logic [DW-1:0] mem [2**AW];
always_ff @(posedge clk) begin
if (wr_en) mem[addr] <= wdata;
rdata <= mem[addr];
end
endmodule
Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It checks reset, enable and the collision case. The RAM waveform uses a separate source that zero-fills memory; the lesson RAM has no initialisation, so an unwritten word is unknown in simulation and not guaranteed zero in hardware.