This is probably more of an iCEstick question than a yosys one, but asking here since I'm using the Icestorm tool chain.
I want to specify startup behavior of my design, which various places on the internet seem to agree is related to the typically named rst
signal. It wasn't obvious to me where such a signal comes from, so I dug into the powerup sequence. Current understanding is from Figure 2 in this document.
After CDONE
is pulled high by the device, all of the internal registers have been reset, to some initial value. Now, I've found plenty of lattice documents about how each type of flip-flop or hard IP receives a reset signal and does something with its internal state, but I still don't quite understand how I specify what those states are (or even just know what they are so I can use them).
For example, if I wanted to bring an LED high for 1 second after powerup (and only after powerup) I would want to start a counter after this reset signal (whatever it is) disables.
Poking around the ice40 family data sheet and the Lattice site, I found this document about using the Global Set/Reset signal. I confirmed this GSR
is mentioned in the family data sheet, referenced on page 2-3 under "Clock/Control Distribution Network". It seems that a global reset signal is usable by one of the global buffers GBUF[0-7]
and can be routed (up to 4 of them) to all LUTs with the global/high-fanout distribution network.
This seems like exactly what I was after, I but I can't find any other info about how to use this in my designs. The document on using the GSR states that you can instantiate a native GSR component like this:
GSR GSR_INST (.GSR (<global reset sig>));
but I can't tell whether this is just for simulation. Am I completely going in the wrong direction here or just missing something? I'm very inexperienced with FPGAs and hardware, so its entirely possible my entire approach is flawed.
I'm not sure if that GSR document actually is about iCE40. The Lattice iCEcube tool interestingly accepts instances of GSR cells, but it seems to simply treat them as constant zero drivers. There is also no simulation model for the GSR cell type in the iCE40 sim library and no description of it in the iCE40 tech library documentation provided by Lattice.
Furthermore, I have built the following two designs with the lattice tools, and besides the timestamp in the "comment field" of the generated bit-stream file, the generated bit-streams are identical! (This test was performed with Lattice LSE as synthesis tool, not Synplify. I had problems getting Synplify to run on my machine for some reason and gave up trying to do so over a year ago..)
This is the first test design I've used:
module top (
input clk,
output rst,
output reg val
);
always @(posedge clk, posedge rst)
if (rst)
val = 1;
else
val = 0;
GSR GSR_INST (.GSR (rst));
endmodule
And this is the second test design:
module top (
input clk,
output rst,
output val
);
assign val = 0, rst = 0;
endmodule
Given this results I think it is safe to say that the lattice tools simply ignore GSR cells in iCE40 designs. (Maybe for compatibility with their other FPGA families?)
So how does one generate a rst signal then? For example, the following is a simple reset generator that asserts (pulls low) resetn
for the first 15 cycles:
input clk;
...
wire resetn;
reg [3:0] rststate = 0;
assign resetn = &rststate;
always @(posedge clk) rststate <= rststate + !resetn;
(The IceStorm flow does support arbitrary initialization values for registers, whereas the lattice tools ignore the initialization value and simply initialize all FFs to zero. So if you want your designs to be portable between the tools, it is recommended to only initialize regs to zero.)
If you are using a PLL, then it is custom to use the PLL LOCK
output to drive the resetn
signal. Unfortunately the "iCE40 sysCLOCK PLL Design and Usage Guide" does not state if the generated LOCK
signal is already synchronous to the generated clock, so it would be a good idea to synchronize it to the clock to avoid problems with metastability:
wire clk, resetn, PLL_LOCKED;
reg [3:0] PLL_LOCKED_BUF;
...
SB_PLL40_PAD #( ... ) PLL_INST (
...
.PLLOUTGLOBAL(clk),
.LOCK(PLL_LOCKED)
);
always @(posedge clk)
PLL_LOCKED_BUF <= {PLL_LOCKED_BUF, PLL_LOCKED};
assign resetn = PLL_LOCKED_BUF[3];
Regarding usage of global nets: You can explicitly route the resetn signal via a global net (using the SB_GB
primitive), but using the IceStorm flow, arachne-pnr will automatically route a set/reset signal (when used by more than just a few FFs) over a global net, if a global net is available.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With