VHDL - why do we need to declare signals for processes? - vhdl

Just revisiting some VHDL and I was wondering inside processes for example, why do we need to declare a signal for a clock for example? Then later on in the code assign it to the port from the entity...
EXAMPLE VHDL:
signal clk_int: std_logic := '1';
BEGIN
clkgen: process(clk_int)
begin
clk_int <= not clk_int after 50ns
end process ckgen
ck_l <= clk_int;
In this example ck_l is a physcial port from the d flip flop yet we create and mess around with clk int then return the value to ck

The reason is that the port ck_l in this case is probably declared with direction out, so It cannot be read from. If you want to read it, like you would need to if you want to have a process that is sensitive to it, you need to use a signal or declare the port as inout or buffer.

Related

In VHDL, Can I use signal'event if signal is not a clock?

I am trying to clean up my VHDL code. I have a signal that is NOT a clk.
Can I write an event change monitor like the following and how do I get it to compile so it can be synthesized? (see code) I have tried several permutations but I cannot get it to compile. Will signal'event compile if signal is not a CLK and if so, how is it done? I see on the web and other literature that it can be done but all examples I see show CLK'event.
signal cntr: unsigned(15 downto 0) := (others => '0');
...
process(CLK):
begin
IF rising_edge(CLK) THEN
if (cntr'event) then
do something;
end if;
or...
if(cntr(0)'event) then
do something;
end if;
END IF;
end process;
I get the following and others
: can't synthesize condition that contains an isolated 'EVENT predefined attribute
rising_edge(CLK) is already an event, making your design synchronous, which is good. As said in comments, only clock signals should use that.
Looking at another even at that time doesn't make sense in synchronous designs, as the 2 signals won't change exactly at the same time, creating a race condition. Or actually a clock within a clock, and the synthesis error...
It may work in simulation, but don't rely on that fact.
The normal way to program in HDL languages is to save the previous value of the signal, on the same clock (for example cntr_d <= cntr) and to compare with that previous value. That allows to find if the signal went up (previously at 0, currently at 1), went down, changed (is different)...
And that method is perfectly fine for synthesis!

Can't handle registered multi driver

I am getting this messege from compiler for all the "busreg" bits:
topld: busshift.vhd: (E463) 'busreg(7)' -- Can't handle registered multi driver.
topld: busshift.vhd: (E446) Can't handle multiple drivers for 'busreg(7)' in selected device.
I was asked to do shift rigister that I can put in put from both side as I choose depends on DIR.
My code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.all;
ENTITY shiftbus IS
PORT
(
busreg : inout std_logic_vector(7 downto 0);
dir,clk : IN std_logic;
pinL,pinR : inout std_logic
);
END shiftbus;
ARCHITECTURE behavioral OF shiftbus IS
BEGIN
busreg<="00000000";
process(clk,dir)
begin
if (rising_edge(clk)) then
if(dir='1') then --1 we input from right
busreg<=busreg(6 downto 0)&pinR;
else-- else is 0 and we input from left
busreg<=pinL & busreg(7 downto 1);
end if;
end if;
end process;
END behavioral;
You have the following line:
busreg <= "00000000";
If you're going to drive this signal low all the time, what's the point of the other logic?
You are driving the signal busreg from two processes: the explicit process and the implicit process busreg <= "00000000";. In other words, you have a short circuit.
A process is a little bit of software that models a little bit of hardware.
So, when you drive a signal from more than one process, you are modelling a signal that is driven from more than one lump of hardware. Normally, if you want to drive a signal from two or more lumps of hardware, you need to be using tristate logic. I think the error message is telling you that the FPGA device you have chosen is not able to implement tristate logic and so it is an error for you to drive a signal from more that one place.
So, why have you written the line busreg <= "00000000";? If you were hoping to reset your shift register, you haven't; you've created a short circuit.
BTW: your process is a sequential process. The sensitivity list of a sequential process should either contain just the clock or, if there is an asynchronous reset, just the clock and the asynchronous reset. dir should not be in your sensitivity list.

Alternative way to implement state machines in VHDL

I have seen many state machines implemented like this one from Altera:
ARCHITECTURE a OF state_machine IS
TYPE STATE_TYPE IS (s0, s1, s2);
SIGNAL state : STATE_TYPE;
BEGIN
PROCESS (clk, reset)
BEGIN
IF reset = '1' THEN
state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
CASE state IS
WHEN ...
An alterantive to that would be this:
ARCHITECTURE a OF state_machine IS
TYPE STATE_TYPE IS (s0, s1, s2);
BEGIN
PROCESS (clk, reset)
VARIABLE state : STATE_TYPE := s0;
BEGIN
IF reset = '1' THEN
state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
CASE state IS
WHEN ...
What are the pros (if any) and cons of doing it the alternative way? I have only seen the alternative in one place and I'm guessing there must be some good reason for that.
I like to keep local things local, so if the state information is needed only within the process, I use a variable. In that case, I also like to declare the state type inside the process:
ARCHITECTURE a OF state_machine IS
BEGIN
PROCESS (clk, reset)
TYPE STATE_TYPE IS (s0, s1, s2);
VARIABLE state : STATE_TYPE := s0;
BEGIN
...
In the rare cases where I need to access the state of an FSM from another process (e.g. interactive state machines), I'll use a signal for storing the state.
The signal vs. variable decision if often a matter of taste. Some developers think that variables are evil and will never use them. Others (like me) use them whenever they can to keep local things local. As a bonus, since variables are more lightweight objects than signals, they also simulate faster.
Using a variable to hold state would mean you couldn't look at state with a waveform viewer.
There might be some synchronization issues with signal inputs used for branching, delta cycle mismatch in zero time models.
Any state machine outputs derived from state would require signals in any event - every concurrent statement has a process equivalent, a VHDL simulator executes processes, processes communicate via signals.
The only pluses that come to mind is that it would be a more compact model (code size) and execute a bit faster.
I often use a variable called state. It keeps the definition hidden, private to just the process that is using it. If you have 2 communicating state machines in one process, they can both have a variable called state local to themselves. Sometimes that works well. Other times it's confusing!
As with many code-style issues, you have to decide on the most readable way to do things. There's no functional reason not to use variables (of any sort, not just state variables).
One other thing you can do with a variable is read the intended next state at the end of the process, which can be useful when you need to reduce latency of outputs. Again, care is needed as you can create long chains of logic inadvertently which can slow the design down.
Variables are great if you are determining a partial sum or intermediate product that is to be used further down in your process in the same clock cycle. However if a variable is not driven every clock cycle then a latch will be inferred. Since you will want the state to be 'remembered' for the next clock cycle then you will get a latch if you use a variable without an assistant register signal. To clarify...
signal state_sig : state_type;
begin
process(clk, rst)
variable state : state_type := s0;
begin
if rst = '1' then
state_sig <= s0;
elsif rising_edge(clk) then
state := state_sig
case state is
when s0 =>
if blah = '0' then
state := s1;
end if;
....
....
end case;
if state = s1 then state := s2; end if;
state_sig <= state;
end if;
end process;
In the above example you are able to avoid going in the state s1 by modifying the state variable before it gets registered. A quick and dirty way of changing the state machine behaviour. However the state_sig signal must be used to 'remember' the state to avoid latch inferral.

VHDL inout ports

I am having trouble creating an entity using inout ports. I tried writing the following code where A is an input and B is an output and it works fine. But as soon as I change A to an inout port, it implements but it won't simulate. Can anyone tell me what the problem is?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Problem2 is
Port ( A : inout integer;
B : out integer
);
end Problem2;
architecture Behavioral of Problem2 is
procedure change (signal A: inout integer; signal B: out integer) is
begin
B<=A after 20 ns;
end change;
begin
change(A=>A, B=>B);
end Behavioral;
The procedure "change" is a driver on A, but doesn't explicitly drive anything, so A will be driven to 'U'. Try this change which should do what you seem to expect:
procedure change (signal A: inout integer; signal B: out integer) is
begin
A <= 'Z';
B <= A after 20 ns;
end change;
Usually, you don't need inout ports. Especially if you are just starting to use VHDL, stick with in or out. Inout is used for modeling tri-state busses. As #wjl points out, you need to assign 'Z' to the signal if you want to be able to read what the other side is writing.
Also, if you are writing procedures for your later reuse, you should not wrap them in an entity and then test the entity. This just causes extra problems (as you are experiencing right now). Instead, call the procedure directly from your test bench, like you would test a procedure (or function) in software.
Are you using Synopsys VCS ?
There is a known limitation in VCS that inout(s) in the entity do not simulate (show up as red)

Error : Identifier 'q' is not readable in architecture of T Flip Flop

I am trying to model a T Flip Flop using VHDL.
library ieee;
use ieee.std_logic_1164.all;
entity tff is
port (
clk: std_logic;
t: in bit;
q: out bit;
qbar: out bit);
end tff;
architecture tff_arch of tff is
begin
process(clk)
begin
if (clk = '1' and t = '1')
then
q <= not q;
qbar <= not qbar;
end if;
end process;
end tff_arch;
But the error i am getting is
Error: CSVHDL0168: tff.vhdl: (line 17): Identifier 'q' is not readable
Error: CSVHDL0168: tff.vhdl: (line 18): Identifier 'qbar' is not readable
The reason of error i think is, i am using "not q", when q has not been initialized. Correct me here, if i am wrong.
And what to do to get around this problem? I have modeled D Flip flop and its test bench waveform correctly using Symphony EDA free version.
In the old days you couldn't read an output, so you had to either:
make it an inout (which is a bit unpleasant as you are fudging the direction you really mean, just so you can read it) - this works, but is not widely used in industry (as far as I'm aware)
make it a buffer, but that had downsides (prior to VHDL-2002) in that you have to make all the rest of the hierarchy of that signal driven by buffers. Almost never used in my experience.
use and intermediate signal (which you can read) and then use an assignment to set the output to the value of that signal. This is the idiomatic way of doing it amongst practising engineers.
Since VHDL-2008 you can read output ports (although the stated intention of this is for it only to be used for verification purposes). You'll probably need a tool switch to enable VHDL-2008 mode. (And it may be that your particular simulator/synthesiser still doesn't support VHDL-2008, which shows the staggering pace of development in the EDA tools world!)
q is an output of the entity.
You can't read an output. It's that simple.
You need an internal version that you use for the feedback loop, and then q <= local_q;
Can't remember VHDL very well, but this might give you a clue:
The problem is that q is only a signal out of your entity, so there is nothing to access when you try to read it.
So, to not solve your homework, think of it this way:
Either you need to have q as an input in order to access it (probably not what you want) or you need to store q (or at least next value of q) internally. This can be done by specifying q (or q_next) as a signal in the architecture part. For example:
architecture tff_arch of tff is
signal q_next: std_logic;
begin
and so on. The same goes for your qbar signal.

Resources