I'm making a simple clock divider in modelsim.
When testing i notice that one if statement is never being executed. Any idea why?
It's the if count > 3 then statement. Modelsim gives the correct value of the counter integer (4, 5, 6, etc) but will never go into the if statement.
------------------------------------------------
-------- CLOCK DIVIDER
------------------------------------------------
entity clock_divider is
port ( clk,reset: in std_logic;
clock_out: out std_logic);
end clock_divider;
architecture bhv of clock_divider is
signal tmp : std_logic:='0';
begin
process(clk,reset,tmp)
variable count: integer:=1;
begin
if(reset='1') then
count := 0;
tmp <= '0';
elsif rising_edge(clk) then
count := count + 1;
if count > 3 then
tmp <= not(tmp);
count := 0;
end if;
end if;
clock_out <= tmp;
end process;
end bhv;
It's because you're using a variable for count. It should be a signal.
Each time the process is carried out in simulation, count will be set to 1.
Variables sometimes get wrongly seen as 'local signals', sort of like local variables in software, which they're not. A design using variables like this will behave differently in simulation to what is produced by a compiler during synthesis. The compiler will promote the variable to a signal but hidden away, with a warning given amongst any other warnings.
Instead, use a signal for count. The HDL design really must imply the actual circuit to be produced, which is DFFs for count.
Variables are useful in the clocked processes of synthesizable designs for (a) reshaping signal values, such as forming buses, or (b) naming nodes along a combinatorial tree. They're not for implying DFFs.
Related
Say I have the following:
always # (posedge clk) beign
...
if (~x) begin
y<=1'b0
end
...
end
And x, driven in another block, happens to be transitioning from 0 to 1 at the moment I'm checking it. How does if() evaluate in this case? Does it take the starting value of x (0) or the final value of x (1)?
I have looked over other answers to similar questions, but none discuss the particular case when the signal is transitioning.
Looking at the waves, the time precision does not allow me to discern if the signal x has settled to 0 or 1.
It depends on how x is driven.
If it is synchronous to the clock signal clk, then the value of x just before the clock edge (0) will be used. In a Verilog simulation, this means that x must be driven off the posedge clk and using a nonblocking assignment:
always #(posedge clk)
x <= some_expression;
Otherwise, you will have a race condition, and the value of x that is used will be indeterminate: it may be 0 or 1.
In VHDL, there are two types for signal assignment:
concurrent ----> when...else
----> select...when...else
sequential ----> if...else
----> case...when
Problem is that some say that when...else conditions are checked line by line (king of sequential) while select...when...else conditionals are checked once. See this reference for example.
I say that when..else is also a sequential assignment because you are checking line by line. In other words, I say that there no need to say if..else within a process is equivalent to when..else. Why they assume when..else is a concurrent assignment?
Where you are hinting at in your problem has nothing to do with concurrent assignments or sequential statements. It has more to do with the difference between if and case. Before we get to that first lets understand a few equivalents. The concurrent conditional assignment:
Y <= A when ASel = '1' else B when BSel = '1' else C ;
Is exactly equivalent to a process with the following code:
process(A, ASel, B, BSel, C)
begin
if ASel = '1' then
Y <= A ;
elsif BSel = '1' then
Y <= B ;
else
Y <= C ;
end if ;
end process ;
Likewise the concurrent selected assignment:
With MuxSel select
Y <= A when "00", B when "01", C when others ;
Is equivalent to a process with the following:
process(MuxSel, A, B , C)
begin
case MuxSel is
when "00" => Y <= A;
when "01" => Y <= B ;
when others => Y <= C ;
end case ;
end process ;
From a coding perspective, the sequential forms above have a little more coding capability than the assignment form because case and if allow blocks of code, where the assignment form only assigns to one signal. However other than that, they have the same language restrictions and produce the same hardware (as much as synthesis tools do that). In addition for many simple hardware problems, the assignment form works well and is a concise capture of the problem.
So where your thoughts are leading really comes down to the difference between if and case. If statements (and their equivalent conditional assignments) that have have multiple "elsif" in (or implied in) them tend to create priority logic or at least cascaded logic. Where as case (and their equivalent selected assignments) tend to be well suited for things like multiplexers and their logic structure tends to be more of a balanced tree structure.
Sometimes tools will refactor an if statement to allow it to be equivalent to a case statement. Also for some targets (particularly LUT based logic like Xilinx and Altera), the difference between them in terms of hardware effiency does not show up until there are enough "elsif" branches though.
With VHDL-2008, the assignment forms are also allowed in sequential code. The transformation is the same except without the process wrapper.
Concurrent vs Sequential is about independence of execution.
A concurrent statement is simply a statement that is evaluated and/or executed independently of the code that surrounds it. Processes are concurrent. Component/Entity Instances are concurrent. Signal assignments and procedure calls that are done in the architecture are concurrent.
Sequential statements (other than wait) run when the code around it also runs.
Interesting note, while a process is concurrent (because it runs independently of other processes and concurrent assignments), it contains sequential statements.
Often when we write RTL code, the processes that we write are simple enough that it is hard to see the sequential nature of them. It really takes a statemachine or a testbench to see the true sequential nature of a process.
I got familiar with a little bit of Verilog at school and now, one year later, I bought a Basys 3 FPGA board. My goal is to learn VHDL.
I have been reading a free book called "Free Range VHDL" which assists greatly in understanding the VHDL language. I have also searched through github repos containing VHDL code for reference.
My biggest concern is the difference between sequential and concurrent execution. I understand the meaning of these two words but I still cannot imagine why we can use "process" for combinational logic (i.e. seven segment decoder). I have implemented my seven segment decoder as conditional assignment of concurrent statements. What would be the difference if I implemented the decoder using process and a switch statement? I do not understand the word sequential execution of process when it comes to combinational logic. I would understand it if it was a sequential machine-a state machine.
Can somebody please explain this concept?
Here is my code for a seven-segment decoder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity hex_display_decoder is
Port ( D: in STD_LOGIC_VECTOR (3 downto 0);
SEG_OUT : out STD_LOGIC_VECTOR (6 downto 0));
end hex_display_decoder;
architecture dataflow of hex_display_decoder is
begin
with D select
SEG_OUT <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when "0100",
"0010010" when "0101",
"0000010" when "0110",
"1111000" when "0111",
"0000000" when "1000",
"0010000" when "1001",
"0001000" when "1010",
"0000011" when "1011",
"1000110" when "1100",
"0100001" when "1101",
"0000110" when "1110",
"0001110" when "1111",
"1111111" when others;
end dataflow;
Thank you,
Jake Hladik
My biggest concern is difference between sequential and concurrent
execution. I understand the meaning of these two words but I still
cannot imagine why we can use "process" for combinational logic (ex.
seven segment decoder).
You are confounding two things:
The type of logic, which can be sequential or combinational.
The order of execution of statements, which can be sequential or concurrent.
Types of logic
In logic design:
A combinational circuit is one that implements a pure logic function without any state. There is no need for a clock in a combinational circuit.
A sequential circuit is one that changes every clock cycle and that remembers its state (using flip-flops) between clock cycles.
The following VHDL process is combinational:
process(x, y) begin
z <= x or y;
end process;
We know it is combinational because:
It does not have a clock.
All its inputs are in its sensitivity list (the parenthesis after the process keyword). That means a change to any one of these inputs will cause the process to be re-evaluated.
The following VHDL process is sequential:
process(clk) begin
if rising_edge(clk) then
if rst = '1' then
z <= '0';
else
z <= z xor y;
end if;
end if;
end process;
We know it is sequential because:
It is only sensitive to changes on its clock (clk).
Its output only changes value on a rising edge of the clock.
The output value of z depends on its previous value (z is on both sides of the assignment).
Model of Execution
To make a long story short, processes are executed as follow in VHDL:
Statements within a process are executed sequentially (i.e. one after the
other in order).
Processes run concurrently relative to one another.
Processes in Disguise
So-called concurrent statements, essentially all statements outside a process, are actually processes in disguise. For example, this concurrent signal assignment (i.e. an assignment to a signal outside a process):
z <= x or y;
Is equivalent to this process:
process(x, y) begin
z <= x or y;
end process;
That is, it is equivalent to the same assignment within a process that has all of its inputs in the sensitivity list. And by equivalent, I mean the VHDL standard (IEEE 1076) actually defines the behaviour of concurrent signal assignments by their equivalent process.
What that means is that, even though you didn't know it, this statement of yours in hex_display_decoder:
SEG_OUT <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when "0100",
"0010010" when "0101",
"0000010" when "0110",
"1111000" when "0111",
"0000000" when "1000",
"0010000" when "1001",
"0001000" when "1010",
"0000011" when "1011",
"1000110" when "1100",
"0100001" when "1101",
"0000110" when "1110",
"0001110" when "1111",
"1111111" when others;
is already a process.
Which, in turn, means
What would be the difference if I implemented the decoder using
process and a switch statement?
None at all.
I was thinking about the signal assignment in generally and I got into a dilemma.
If I have some project in which I have the following code:
ARCHITECTURE wait_example of wait_example IS
SIGNAL sendB, sendA : std_logic;
BEGIN
sendA <= ‘0’;
A : PROCESS
BEGIN
-- something
END PROCESS A;
B : PROCESS
BEGIN
-- something
END PROCESS B;
C : PROCESS
BEGIN
-- something
END PROCESS C;
And so on... I was thinking about when will the "sendA <='0';" part occurs? Only once in the beginning? Will it constantly reset sendA to 0? Or something else?
Thanks in advance,
Bojan Matovski
In addition to David Koontz good answer, it may be added that even through the
sendA <= '0' is only executed once, it will continuously drive sendA to
'0'. In test bench design, the final value on sendA is given by the resolution function
over all drives of sendA, where as in synthesizable design there should not be multiple drivers.
If you also try to drive sendA from one of the processes like:
sendA <= '0';
A : PROCESS
BEGIN
wait for 100 ns;
sendA <= '0';
wait for 100 ns;
sendA <= '1';
wait for 100 ns;
sendA <= 'Z';
wait;
END PROCESS A;
Then you will get the final value of sendA as:
0 ns: 'U', as result of resolution by '0' and 'U' from the yet unassigned
signal driven in A process.
100 ns: '0', as result of resolution by '0' and '0'
200 ns: 'X', as result of resolution by '0' and '1'
300 ns: '0', as result of resolution by '0' and 'Z'
Waveform is shown below.
Any concurrent statement has an equivalent process. Without a signal on the right hand side it's equivalent is a process terminated by a WAIT; statement. It'll execute once.
Although VHDL is a hardware description language, what you write down is a little different to the real circuit.
Concurrent assignments generally stand for combination logic. But that doesn't mean that you can't modify sendA's value after you make a concurrent assignment like sendA <= '0';, as MortenZdk mentioned. The value of signals with type std_logic are determined by a function called resolved function because std_logic is a resolved type. For example, if sendA has two drivers associated with it(sendA <= '0'; & sendA <= '1'; in two different processes), it'll get a 'X' eventually.
EDIT:
See also about delta time and multiple drivers.
So sample loop:
do i=1,1
print *,i
enddo
print *,i
gives me 2 as the final value of i. How can I set up Intel Fortran for Visual Studio on Windows to give me a final value of 1 for i?
This has been the way that Fortran loops work for decades and you can't simply change this with a compiler option. The Fortran standard clearly states:
8.1.4.4.1 Loop initiation
(2) The DO variable becomes defined with the value of the initial parameter m1.
(3) The iteration count is established and is the value of the expression
MAX (INT ((m2 – m1 + m3) / m3), 0)
Here m1, m2 and m3 are the three parameters in the loop-control: [,] var = m1,m2[,m3], Given your example of i=1,1 (m3 is implicitly 1 if omitted) the iteration count is MAX(INT((1-1+1)/1),0) which evaluates to 1, i.e. the loop should get executed once. i is initialised to 1 as per (2).
8.1.4.4.2 The execution cycle
The execution cycle of a DO construct consists of the following steps performed in sequence repeatedly until termination:
(1) The iteration count, if any, is tested. If the iteration count is zero, the loop terminates and the DO construct becomes inactive. If loop-control is [ , ] WHILE (scalar-logical-expr), the scalar-logicalexpr is evaluated; if the value of this expression is false, the loop terminates and the DO construct becomes inactive. If, as a result, all of the DO constructs sharing the do-term-shared-stmt are inactive, the execution of all of these constructs is complete. However, if some of the DO constructs sharing the do-term-shared-stmt are active, execution continues with step (3) of the execution cycle of the active DO construct whose DO statement was most recently executed.
Fortran tests if the remaining iteration count is greater than zero, not if the DO variable is less than (greater than) the end value.
(2) If the iteration count is nonzero, the range of the loop is executed.
(3) The iteration count, if any, is decremented by one. The DO variable, if any, is incremented by the value of the incrementation parameter m3.
The DO variable is always incremented as an iteration of the loop is being executed. Thus after the first execution i becomes incremented by 1 which evaluates to 2.
Except for the incrementation of the DO variable that occurs in step (3), the DO variable must neither be redefined nor become undefined while the DO construct is active.
8.1.4.4.4 Loop termination
When a DO construct becomes inactive, the DO-variable, if any, of the DO construct retains its last defined value.
The last defined value is 2. Thus after the DO loop has ended, i is equal to 2.
I've pulled the text out of ISO/IEC 1539:1991 (a.k.a. Fortran 90) but one can also find pretty much the same text in §11.10.3 of ISO/IEC 1539:1980 (a.k.a. ANSI X3J3/90.4 a.k.a. FORTRAN 77; sans the WHILE stuff which is not present in F77) as well as in §8.1.6.6 of ISO/IEC 1539-1:2010 (a.k.a. Fortran 2008).
You can't, because that's how DO works; it stops when the control variable exceeds the limit.
In general, in pretty much any language with a FOR/DO counting loop, you should only use the loop control variable inside the loop body, and treat it as undefined elsewhere, even if you can't actually limit its scope to the body.
In your case, I would use a different variable to keep track of the actual last value of i in any iteration:
lasti = 0
do i=1,1
print *,i
lasti = i
enddo
print *,lasti