I am currently studying VHDL about SR Latch, and there comes to a part which I don't understand.
Can anyone explain What does ATTRIBUTE keep: boolean mean and what does it do in VHDL?
Thank you.
Warning heavy Xilinx bias...
The attributes for the VHDL are different for different tools and even change between versions of the same tools. The "keep" attribute for Xilinx used to insure that in the Vivado synthesis process the signal is not optimized away. It has been renamed recently to "syn_keep" to avoid confusion. I've used similar attributes to fix build issues before in which the tools make false assumptions.
NOTE: In order to avoid optimization during the implementation for Xilinx use "dont_touch".
Example:
A clock coming into the FPGA needs to be buffer through the Xilinx BUFG, but I needed the raw signal for a specific IP core. So I split the route, buffer the clock and fed the raw clock signal to the IP. The Vivado 2016.4 tool optimized out the unbuffered route creating a time constraint critical warnings and misbehavior on the hardware. The issue was found by tracing through the synthesis design schematics, observing the proper routing, and then viewing the implementation design schematic and seeing the route is altered. I fixed this by adding the dont_touch attribute to the unbuffered signal.
attribute dont_touch : boolean;
attribute clock_signal : string;
attribute dont_touch of clk_in : signal is true;
attribute clock_signal of clk_in : signal is "yes";
...
CLK_BUFG: component BUFG
port map (
I => clk_in,
O => buf_clk_in
);
It is a user defined attribute, thus not part of the VHDL standard itself. It is typically used to instruct the synthesis tool that it should keep a certain signal, for example being a flip-flop, even through the synthesis tool may determine that the signal can be removed during optimization.
For Altera Quartus synthesis tool, see this description: keep VHDL Synthesis Attribute
Related
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.
I have a Testbench that uses VHDL-2008's hierarchical accesses to test the good behaviour of my architecture, which I wrote in VHDL.
Like this :
TEST_SIGNAL <= << signal uut_0.signal_to_test : std_logic_vector(7 downto 0) >>;
This worked great but now what I want is to use the same testbench to simulate a verilog netlist corresponding to my synthesized design :
VHDL Testbench
Verilog netlist
Corresponding library
However, my hierarchical accesses don't work now ("Target of VHDL external name is not a vhdl object." error).
This is normal (I guess) but do you have any idea how I could work my way around this, i.e. still observe internal entities of my design? (Other than declaring everything I want to watch as outputs of my UUT...)
(I use ModelSim SE 10.3c to simulate)
Let's say I have a signal, I can either assign a initial value of zero OR I can set it to zero upon RESET. I've seen my co-workers using the two method interchangeably. I just want to see others opinion on this.
Example (using initial value):
architecture arch of xxx is
signal flag : STD_LOGIC := 0;
begin
process (clk) begin
if rising_edge(clk) then
-- do something
end if;
end process;
end arch;
Example (using reset value):
architecture arch of xxx is
signal flag : STD_LOGIC;
begin
process (clk,rst) begin
if (rst = '1') then
flag <= '0';
elsif rising_edge(clk) then
-- do something
end if;
end process;
end arch;
If possible, use a dedicated reset signal, for several reasons:
Designs using complex clock generation may require that a module is held idle
(reset) until the clock is stable. Using initial values with an unstable but
running clock may change the initial value from the expected.
A module that interfaces to other or external modules may get protocol
violations on an interface during startup, and to avoid wrong operation or
hangup due to protocol violations, it may be required to hold the module in
reset until the protocol operation is well defined in the interface.
Restart of the entire system, or part of the system, is possible by asserting
reset, instead of having to reload the entire FPGA, which takes much longer
time, and may be more complicated if it requires CPU interaction.
Some FPGA technologies, for example Altera partial reconfiguration, does not
support initial values for the modules used in partial reconfiguration.
Reuse of modules is therefore easier if only reset is used.
Simulation of different start/restart conditions is easier when it is
possible to apply reset, and continue the same simulation sequence. If
initial value is used, then the entire simulation must be restarted.
Apply reset to as few flip-flops as possible, for the resource reasons that Russell
points out. Also, applying it to only the required flip-flop, makes it easier
to catch bugs and oversights in the design during simulation, since unknown X
values may then appear. The reset should be asynchronous, since most FPGA and
ASIC technologies have flip-flops with dedicated reset input, and the reset
will then not slow down the timing of the synchronous design part, by insertion of logic to apply a reset value. The slow down can be seen in for example Altera Cyclone V, where logic is inserted in the data path due to the synchronous reset through a MLABCELL, as shown in the data path timing report here:
A flip-flop using asynchronous reset does not have this extra delay in the data path, as can be seen in figure through this link.
The process for flip-flops with reset should be written with the reset part as:
process (clk, rst) begin
if rising_edge(clk) then
-- Flip-flops updated at clock
end if;
if (rst = '1') then
-- Flip-flops reset
end if;
end process;
This coding style makes it possible to apply reset to only some of the
flip-flops updated at the rising clock, while the remaining flip-flops are
implemented without reset.
The combined if-then-elsif-end if in question code, actually specified that
the state is held during reset for flip-flops that are not reset, since the
rising_edge(clk) part of the if does then not take effect. This is
probably not the intended implementation.
For proper timing, the reset signal (rst) should be synchronized to the clock
(clk), at least for deassertion (1 to 0), so recovery and removal time are not violated.
'Value after FPGA configuration' vs 'Value after reset'
The initial value will be the value the signal will get after the FPGA configuration.
The value affected in case of a reset will be... the value the signal will get in case the reset signal is asserted :-)
About the signal value after FPGA configuration
From Xilinx "Large FPGA Methodology Guide" page 31 :
FPGA devices have dedicated global set/reset signals (GSR). At the end of device
configuration, the GSR is automatically asserted to initialize all registers to the initial state specified in the HDL code.
Every register is at a known state at the end of configuration. You do not need to code a global reset for the sole purpose of initializing the device.
Of course, you need to trust the FPGA you use about this initial value. People often prefer to have a reset on control signals to ensure this out of configuration initial value, even if this is normaly not required...
To reset or not to reset
Maybe you need a reset for specific other reasons :
coding rules that enforce this
the necessity to set this signal back to a known value without having to reconfigure the FPGA
If you need this reset, it will probably be asserted when the FPGA go out of configuration, and the initial value will then be useless, so it is probably better to not use it.
Hope this helps.
I'm of the opinion that you should not reset any signals that do not need it. Only things like state machines or counters should be reset. Adding resets to everything means that the tools will have to add routing resources to hook up all of these resets. So for example I almost never reset any signal that just holds data, or some enable signal that will only be active for one clock cycle anyway.
Regarding initialization, I initialize every register that I infer. This can be easily checked by looking at a modelsim waveform. Red = Bad. This takes no additional resources to achieve, but it ensures that the FPGA starts up in a known-condition.
Using FSM in VHDL you have to declare the states, that are going to be used:
type state_values is (ST0,ST1,ST2,ST3,ST4,ST5,ST6,ST7,ST8,ST9,ST10,ST11,ST12,ST13,ST14,ST15,ST16);
signal pres_state, next_state: state_values;
I've tried used the states as a LOGIC_VECTOR, but then the state definition wouldn´t be necessary. When using a Structural implementation, is there a way to use the state definition betweeen the components? Is there a way to implement a FSM with components?
Declare your state type in a package, then you can use the package in both components and they will share the state type; you can interconnect them with signals and ports of that type, etc.
But my question is why? The single process form of state machine is generally simpler and more reliable (it has just "state" instead of "present_state" and "next_state"). What purpose is there in splitting a SM into not just several processes, but several components?
I am trying to re-use netlists in other designs without the success.
I have a component which is translated to the netlist:
entity c is
port (... sel : in std_logic_vector(31 downto 0); ... );
In the design I am using just sel(4 downto 0).
The synthesis tools notices this behaviour and gives a warning:
'WARNING:Xst:647 - Input sel<31:5> is never used ..
I am generating netlist with properties:
keep hierarchy = true
add I/O buffers = off
Whenever I want to instantiate this netlist as an black-box module in other circuit I got an error:
ERROR:NgdBuild:76 - cannot be merged into block because one or more pins on the block, including pin "sel<31>", were not found in the file.
How can I preserve the size of sel?
I should mention that the sel needs to be 32bits width since it's connected to the bus.
You could try driving the unused input ports to zero.
Can you use the component directly instead of as a pre-synthesised black-box?
You may get things to work by putting a KEEP attribute (see your synth tools manual) on the port. I've only ever tried this on signals, but it may work.
This sort of task is often described as "pushing on the rope" of the synthesiser, as it's such a pain to get it to not be as celever as it wants to be (and then in the next release of tools you need a different attribute :)