I understand that default signal assignment is useful (even necessary) in VHDL to avoid incomplete assignment and inferred latches. I can't discover whether it is also necessary for variables.
Consider this block of code:
test_sequencer : process(fpga_clock)
variable sequencer_count : unsigned(3 downto 0) := (others => '0');
begin
if rising_edge(fpga_clock) then
start_writing <= start_writing;
start_reading <= start_reading;
sequencer_count := sequencer_count; -- is this line necessary
if not_every_fpga_clock = '1' then
case sequencer_count is
when x"4" =>
start_writing <= '1';
when x"12" =>
start_reading <= '1';
when others =>
null;
end case;
if sequencer_count /= 15 then
sequencer_count := sequencer_count + 1;
end if;
end if;
end if;
end process;
Is the line marked "is this line necessary?" required? I understand that it must be there if sequencer_count
is a signal. Is it necessary when sequencer_count
is a variable?
First, default assignments only prevent latches if no clock is present - ie: combinational logic.
Within register/flip-flop logic (code following the "if rising_edge(clock)"), default assignments prevent hold conditions - which are a normal part of register logic. A latch will never be produced from code under an "if rising_edge(clock)".
OTOH, what you have I call identity assignment:
start_writing <= start_writing;
start_reading <= start_reading;
sequencer_count := sequencer_count;
Identity assignments are not default assignments and specify feedback explicitly. These do not prevent latches in combinational logic.
A default assignment assigns either a literal value or a value from the output of a combinational logic signal:
start_writing <= '0';
sequencer_count := "0000";
LedState <= LedNext;
Note that for a variable declaration in a process, the initialization is only run when the process is elaborated - which is at the start of time and not each time when the process runs:
variable sequencer_count : unsigned(3 downto 0) := (others => '0');
This is different from subprogram execution that creates and initializes the variables each time it is called.
None of these lines are necessary:
start_writing <= start_writing;
start_reading <= start_reading;
sequencer_count := sequencer_count; -- is this line necessary
None of them do anything at all. In complete assignment and latch inference is only a problem with combination logic. This is (synchronous) sequential logic. You never need to worry about complete assignment with (synchronous) sequential logic.
Why is this? Well, in the case of combinational logic, if you don't have complete assignment, there will be some combination of inputs that results in a path through the process being followed in which an output of the process (a signal driven by it) does not get assigned a value. Any signal will keep its value until a new value is assigned. Therefore, in the case of incomplete assignment, it will be necessary for the resulting circuit to remember (to store) the state of that output. Therefore, some kind of circuit that can store information will be synthesised. That will not be a flip-flop, because there are no clocks, no rising_edge
function calls etc; instead, latches will be synthesised to do that remembering. That is doubly bad, because (a) latches are fundamentally bad anyway and (b) your were wanting combinational logic but got sequential. That's a bug.
However, in a (synchronous) sequential circuit, you already have storage. Flip-flops can be considered as 1-bit memories. Therefore, you don't need to ever worry about complete assignment in a (synchronous) sequential process. You are expecting the resulting circuit to be able to store things.
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