3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-11 03:33:36 +00:00

ice40: simulate SPRAM poweron delay in cells_sim

Makes the SB_SPRAM simulation model slightly more accurate, including a coarse
simulation of how the block behaves when modifying the various power/sleep
state control lines.
This commit is contained in:
bobtwinkles 2020-12-02 22:48:33 -08:00
parent 58e8901fee
commit 2e1562a28a

View file

@ -2503,25 +2503,73 @@ module SB_SPRAM256KA (
`ifndef BLACKBOX
`ifndef EQUIV
reg [15:0] mem [0:16383];
wire off = SLEEP || !POWEROFF;
// We provide a very coarse-grained simulation of the internal logic in the
// SPRAM, emulating the power-on delays of 2 virtual power domains: the
// "standby" logic and the "main" logic. The main logic takes longer to boot,
// and provides memory retention. Standby logic is ready faster but requires
// more power to operate, as it maintains memory contents.
//
// For details on the canonical power states, please consult Lattice FPGA
// Technical Note TN2022.
//
// First we need some counters for the number of simulation ticks until the
// respective power domain is enabled. These counters are reset to the full
// duration of the delay every time the respective power domain is disabled
// and count down once per simulation tick.
integer standby_power_delay = 0;
integer main_power_delay = 0;
// We also define some handy wires which represent the state of our simulated
// power domains.
wire power_inputs = POWEROFF & ~SLEEP & ~STANDBY;
wire main_power = (main_power_delay == 0) & power_inputs;
wire standby_power = (standby_power_delay == 0) & power_inputs;
wire off = ~(standby_power & main_power);
integer i;
always @(negedge (main_power_delay == 0)) begin
while (main_power_delay != 0) begin
#100 main_power_delay = main_power_delay - 100;
end
end
always @(negedge (standby_power_delay == 0)) begin
while (standby_power_delay != 0) begin
#100 standby_power_delay = standby_power_delay - 100;
end
end
always @(negedge POWEROFF) begin
for (i = 0; i <= 16383; i = i+1)
mem[i] = 16'bx;
end
always @(posedge CLOCK, posedge off) begin
always @(posedge POWEROFF) begin
main_power_delay = 41800;
end
always @(negedge SLEEP) begin
main_power_delay = 41800;
end
always @(negedge STANDBY) begin
standby_power_delay = 1700;
end
always @(posedge CLOCK, main_power, standby_power) begin
if (off) begin
DATAOUT <= 0;
end else
if (STANDBY) begin
DATAOUT <= 16'bx;
// Leave DATAOUT alone in this case, as the memory is specified to leave
// outputs unchanged when entering the standby state. (TN2022-1.2)
end else
if (CHIPSELECT) begin
if (!WREN) begin
DATAOUT <= mem[ADDRESS];
end else begin
end else
if (main_power & standby_power) begin
if (MASKWREN[0]) mem[ADDRESS][ 3: 0] <= DATAIN[ 3: 0];
if (MASKWREN[1]) mem[ADDRESS][ 7: 4] <= DATAIN[ 7: 4];
if (MASKWREN[2]) mem[ADDRESS][11: 8] <= DATAIN[11: 8];