Comparison with 0 or 1, to detect high impedence - vhdl

I know that its not allowed to compare with X or Z in a synthesizable VHDL code. But is it allowed to write a code in which I compare a signal to 0 or 1 to detect an Z and suspend the operation? The code is as follows:
process(clk)
begin
if rising_edge(clk ) then
if(rst = '0') then
reg_0 <= (others => 'Z');
elsif(btf_start = '1') then
reg_0 <= "ZZ" & frame_in;
elsif(t_btf_finish = '1') then
reg_0 <= (others => 'Z');
end if;
end if;
end process;
process(clk)
begin
if rising_edge(clk) then
if(reg_0(0) = '0' or reg_0(0) = '1') then
-- DO SOME OPERATIONS
else
-- DO NOTHING
end if;
end if;
end process;

No, this won't work. Physical digital signals can have exactly 2 states, '0' and '1'. The states are defined by the voltage on the signal: less than some voltage is a '0', greater than that voltage is a '1'. Even floating (high-z) signals will have some voltage that will be interpreted as a '1' or '0'.
'Z' basically says that a certain source isn't driving the signal, allowing a different source to drive a '0' or '1'. For the case when no source is driving the signal, the signal will usually have a pull-up or pull-down resistor to keep it in a defined '1' or '0' state by default.

Related

VHDL - Inferred Latch With Reset - FSM

I have an issue with this process where if I include a reset statement, I get an inferred latch. However, if I do not include the reset statement, I do not get an inferred latch on duty_cycle_triangle.
SIGNAL duty_cycle_triangle : INTEGER := 0;
SIGNAL count_up : STD_LOGIC;
SIGNAL tick_zero : STD_LOGIC;
triangle_count: PROCESS(clk, reset signal, tick_zero)
BEGIN
IF (reset = '1') THEN
duty_cycle_triangle <= 0;
ELSIF (RISING_EDGE(clk)) THEN
IF (tick_zero = '1') THEN
IF (count_up = '1') THEN
duty_cycle_triangle <= duty_cycle_triangle + 2;
ELSE
duty_cycle_triangle <= duty_cycle_triangle - 2;
END IF;
END IF;
END IF;
END PROCESS;
I am trying to design an FSM that will output a triangle wave using a PWM and an FSM shown below:
FSM_comb: PROCESS(currentState, duty_cycle_triangle)
BEGIN
CASE currentState IS
WHEN triangle_up =>
PWM_enable <= '1';
count_up <= '1';
IF (duty_cycle_triangle > 99) THEN
nextState <= triangle_down;
ELSE
nextState <= triangle_up;
END IF;
WHEN triangle_down =>
PWM_enable <= '1';
count_up <= '0';
IF (duty_cycle_triangle < 1) THEN
nextState <= triangle_up;
ELSE
nextState <= triangle_down;
END IF;
END CASE;
END PROCESS;
FSM_seq: PROCESS(clk, reset)
BEGIN
IF (reset = '1') THEN
currentState <= triangle_up;
ELSIF (RISING_EDGE(clk)) THEN
currentState <= nextState;
END IF;
END PROCESS FSM_seq;
Basically, after every "tick" I want the duty cycle of the triangle wave to increase by 2. After the duty cycle reaches 100, I want the duty cycle to decrease by 2 until the duty cycle reaches 0. Once the duty cycle reaches 0, I want the duty cycle to start increasing from 0 again until it reaches 100 and it starts over.
Does anyone see any problems with my code or can anyone point me in the right direction to correcting any issues?
If you want to create a sequential process, only include a reset and a clock in your sensitivity list. I suspect that it's inferring the latch because you're including too many signals in this process:
triangle_count: PROCESS(clk, reset signal, tick_zero)
It should just be
triangle_count: PROCESS(reset, clk)
The tools don't see that as a sequential process and make it combinational and that's how you get your latch.
Without trying it out i'm wondering if when the reset statement is removed, the tool is recognising the process as a synchronous process and inferring registers. In this case you don't need to explicitly define duty_cycle_triangle for each outcome of the process as the value is stored in a register.
With the reset statement included it may be treating the process as combinatorial and therefore inferring latches to store the state of duty_cycle_triangle when it's not explicitly defined.
Either way I agree with Russell's suggestion of changing the process sensitivity list which should get rid of the latch.

Signal becomes 0X00 from 0100

I am working on a Program Counter that must be added 4 in each rising edge of a clk:
Code:
if_CounterSum <= MemAddr + 4;
process (Clk, Reset)
begin
if Reset = '1' then
MemAddr <= (OTHERS => '0');
elsif rising_edge(Clk) then
MemAddr <= if_CounterSum;
end if;
end process;
When simulating in ISIM,
After Reset is set to 0:
Initial state:
MemAddr = 0 (0000)
if_CounterSum = 4 (0100)
First CLK rising_edge:
MemAddr = X (0X00)
if_CounterSum = X (XXXX)
I have been working on this "simple" thing for some hours, I have tried:
Change the +4 line to synchronous too (Into the process) but problem kept.
Some other stuff that didn't worked.
How can I fix that X? I have tested other numbers instead of 4 and as I guessed all '1's in if_CounterSim where converted in 'X's after the assignment.
You have not included all of the code, so below is a guess.
The problem is probably a result of VHLD resolution of the signal, whereby multiple conflicting drivers of the same signals as for example both '0' and '1' will result in 'X', but where two drivers of '0' will result in '0'.
So look for all places in the module where MemAddr and if_CounterSum are assigned, and remove those unnecessary assigns.
When assigning a signal outside a process you literally connect it to the right side of the arrow.
When assigning a signal inside a synchronous process you implement flip flops to assign a value to your signal on clock edges.
In your case, I suggest you put if_CounterSum <= MemAddr + 4; in your process. This way, the increment will be done at each clock rising edge.
process (Clk, Reset)
begin
if Reset = '1' then
MemAddr <= (OTHERS => '0');
elsif rising_edge(Clk) then
MemAddr <= MemAddr + 4;
end if;
end process;
If you really need the if_CounterSum you can add if_CounterSum <= MemAddr outside the process this time (because it would be wired).

Is the use of rising_edge on non-clock signal bad practice? Are there alternatives?

I am working on a VHDL design and I have it working, but the code is pretty ugly and the fact that it seems that I am trying to work around the language's design to accomplish my goal makes me feel like something is wrong. I'm pretty new to VHDL, but I have been working on smaller chunks of the project for nearly a month so I have the general idea. However, This part is a bit more complex.
I need a process that will create a one clock period long pulse (LOAD_PULSE) after the rising edge of a signal (END_ADC), but not until 4 clocks has passed from the latest rising edge of that signal (END_ADC) OR the falling edge of a second signal (LVAL).
To accomplish the wait period, I have built a timer module that counts microseconds and periods, here:
entity uS_generator is
generic(
Frequency : integer := 66 -- Frequency in MHz
);
Port (
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
T_CNT : out integer range Frequency downto 1 := 1;
uS_CNT : out integer range 65535 downto 0 := 0
);
end uS_generator;
architecture behavior of uS_generator is
signal T_CNT_INT : integer range Frequency downto 1 := 1; -- Counter for 1 uS
signal uS_CNT_INT : integer range 65535 downto 0 := 0;
begin
COUNT: process(CLK, RESET)
begin
if RESET = '1' then
T_CNT_INT <= 1;
uS_CNT_INT <= 0;
elsif rising_edge(CLK) then
if T_CNT_INT = (Frequency - 1) then -- Increment one clock early so last rising edge sees one uS elapsed.
uS_CNT_INT <= uS_CNT_INT + 1;
T_CNT_INT <= T_CNT_INT + 1;
if uS_CNT_INT = 65535 then
uS_CNT_INT <= 0;
end if;
elsif T_CNT_INT = Frequency then
T_CNT_INT <= 1;
else
T_CNT_INT <= T_CNT_INT + 1;
end if;
end if;
end process COUNT;
T_CNT <= T_CNT_INT;
uS_CNT <= uS_CNT_INT;
end behavior;
The processes I'm using for the pulse generation portion of the design are as follows:
loadPulseProc: process(PIXEL_CLK, END_ADC, RESET)
begin
if RESET = '1' then
PULSE_FLAG <= '0';
LOAD_PULSE <= '0';
elsif rising_edge(END_ADC) then
PULSE_FLAG <= '1';
end if;
if rising_edge(PIXEL_CLK) then
if PULSE_FLAG = '1' and END_ADC = '1' and LVAL <= '0' and ADC_TMR_T >= 4 and LVAL_TMR_T >= 4 then
LOAD_PULSE <= '1', '0' after PIXEL_CLK_T;
PULSE_FLAG <= '0';
end if;
end if;
end process loadPulseProc;
ADCTimerProc: process(END_ADC, RESET)
begin
if RESET = '1' then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process ADCTimerProc;
LVALTimerProc: process(LVAL, RESET)
begin
if RESET = '1' then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process LVALTimerProc;
PIXEL_CLK_T is the period of the clock, 15.152 ns.
This design works, simulation shows that it does as I require, but only after significant hassle avoiding errors due to using multiple rising_edge of falling_edge calls by separating them into separate if statements that really should be together. As far as I've read using rising_edge and falling_edge seems to be reserved for clocks only, so is this just bad practice? How can avoid this behavior but still create the same output?
Thanks!
Yes, rising_edge()/falling_edge() should only be used for clock signal. While it works in simulation it can cause problems and unintended hardware in synthesis.
Synthesis tools infer a clock from the function's argument and place such signals/wires on special tracks in the FPGAs (assuming you are targeting an FPGA for your design). The tool will further infer special clock buffers and warn if your input clock pin is not a clock capable pin.
Introducing several clocks can lead to asynchronous designs and make it vulnerable for cross clock faults.
Detecting a rising or falling edge on a signal is done by an edge detection circuit like the following which compares the signal in the previous clock cycle to the current value.
Needed signals:
signal mySignal_d : std_logic := '0';
signal mySignal_re : std_logic;
Needed logic:
mySignal_d <= mySignal when rising_edge(Clock);
mySignal_re <= not mySignal_d and mySignal;
This first line translates to an 1-bit D-flipflop (You could also use a process). The second lines generates a one cycle strobe signal when mySignal changes from low to high. I'm using *_d to indicate a delayed signal of the original input and *_re for rising edge.
The generated signal is still synchronous to Clock.

Communication between processes in VHDL

I have problems on communicating between the processes. I used to use flag and clearFlag to tackle this, but it's kind of annoying and not looking good. What is the best practice to handle this? Here is a sample code on how I did it before:
Proc_A : process (clk, reset, clrFlag)
begin
if clrFlag = '1' then
flag <='0';
elsif reset = '0' then
A <= (others => '0');
elsif rising_edge (clk) then
A <= in;
flag <= '1';
end if;
end process;
Proc_B : process (clk, reset)
begin
if reset = '0' then
B <= (others => '0');
elsif rising_edge (clk) then
if flag = '1' then
B <= data;
clrFlag <= '1';
else
clrFlag <= '0';
end if;
end if;
end process;
This way works but I don't think it is nice method. I have to write a flag and clrFlag couple to do this task. All I want to do is when something happened (e.g. A <= in;), it triggers another proc, Proc_B for example, to run once or a number of times. What is the best practice to this problem? Thanks!
For simulation, you can make a process wait on a signal:
Proc_B : process
begin
wait until flag'event;
B <= data;
end process;
and just write the flag with its inverse every time you need something to happen.
In synthesisable logic, you either have to exchange flag signals, as you do, or use some other higher-level communication (like a FIFO, messagebox, or similar).
However, if all your proc_b logic takes place in a single cycle - so you can guarantee not to miss a flag, and to be able to keep up even if flag is asserted all the time (as it looks like you do) - you can do this (and combine the two processes):
Proc : process (clk, reset, clrFlag)
begin
flag <='0';
if reset = '0' then
A <= (others => '0');
B <= (others => '0');
elsif rising_edge (clk) then
if some_trigger_event = '1' then
A <= in;
flag <= '1';
end if;
-- recall that due to VHDL's scheduling rules, this "if" will take place
-- one clock cycle after the flag is written to, just as if it were in a
-- separate process
if flag = '1' then
B <= data;
end if;
end if;
end process;
Side note - your code is not ideal for synthesis... you really only want the reset part outside the clocked part:
Proc_A : process (clk, reset)
begin
if reset = '0' then
A <= (others => '0');
elsif rising_edge (clk) then
if clrFlag = '1' then
flag <='0';
else
A <= in;
flag <= '1';
end if;
end process;

Undesiderated 1-bit latch (VHDL)

I'm programming a N-bit non-restoring divider, but I faced a little problem.
I have an Operative Part (combinatorial) and a Control Part (Finite State Machine).
The Control Part has a 2 processes FSM, 1 for updating the next state and 1 for the "state sequence".
update: process(clk_in, next_state)
begin
if rising_edge(clk_in) then
current_state <= next_state;
end if;
end process;
And this is the second process:
control: process(current_state, start, S_in, counted)
variable sub_tmp : STD_LOGIC := '0';
begin
[...]
sub <= sub_tmp; -- sub is an output signal of my entity that goes in the Operative Part
case current_state is
when idle =>
if start='1' then
next_state <= init;
else
next_state <= idle;
end if;
when init =>
-- [...]
next_state <= subtract;
when subtract =>
en_A <= '1';
sub_tmp := '1';
next_state <= test;
when test => -- shift
en_Q <= '1';
if S_in='0' then
sub_tmp := '1';
else
sub_tmp := '0';
end if;
if counted=N/2-1 then
next_state <= finished;
else
next_state <= operation;
end if;
when operation =>
en_A <= '1';
next_state <= test;
when finished =>
stop <= '1';
next_state <= idle;
end case;
end process;
As you can see, I need to change the value of the sub ONLY in 2 cases (subtract and test), while I don't have to change in the other cases.
The problem is that when I try to synthesize this code it turns out that sub_tmp is a LATCH, but I don't want a latch.
I need to do something like this:
state 1 => set sub to '1' or '0' (depending on another input)
state 2 => do other operations (but sub must remain the value set before) and return to state 1
etc...
To clarify more: in certain states of my FSM (not all of them) I set the value of a variable (let's call it sub_tmp). In other states I don't change its value. Then let's say I have an output PIN called "sub_out". Now, independently of the variable value, I want to output its value to this pin (sub_out <= sub_tmp; or similar).
What am I missing?
What you are missing is the behavior you describe IS a latch. Anything with memory (ie: "in other states I don't change it's value") is either a latch or a register (flip-flop). If you don't want a latch or a register, you need to assign a specific value to the signal in each and every code path, and not let it 'remember' it's previous state.

Resources