VHDL Shift Register Program different results when using signals and variables - vhdl

So I've been using VHDL to make a register, where it loads in the input X if LOAD is '1' , and outputs the data in serial fashion , basically a parallel in serial out register. The input X is a 4 bit ( 3 downto 0 ) input , what I want to make the program do is constantly output 0 when the register has successfully output all the btis in the input.
It works when "count" is defined as a signal , however , when count is defined as a variable , the output is a constant 0 , regardless of whether load is '1' or not. My code is as shown:
entity qn14 is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
LOAD : in STD_LOGIC;
X : in STD_LOGIC_VECTOR (3 downto 0);
output : out STD_LOGIC);
end qn14;
architecture qn14_beh of qn14 is
type states is ( IDLE , SHIFT );
signal state : states;
signal count: STD_LOGIC_VECTOR(1 downto 0);
begin
process(clk , reset)
variable temp: STD_LOGIC;
variable data: STD_LOGIC_VECTOR(3 downto 0);
begin
if reset = '1' then
state <= IDLE;
count <= "00";
output <= '0';
elsif clk'event and clk = '1' then
case state is
when IDLE =>
if LOAD = '1' then
data := X;
output <= '0';
state <= SHIFT;
elsif LOAD = '0' then
output <= '0';
end if;
when SHIFT =>
if LOAD ='1' then
output <= '0';
elsif LOAD = '0' then
output <= data( conv_integer(count) );
count <= count + 1;
if (count >= 3) then
state <= IDLE ;
end if;
end if;
end case;
end if;
end process;
end qn14_beh;
Hoping to seek clarification on this.
Thank you.

This may not fully answer your question, but I will cover several issues that I see.
The elsif LOAD = '0' then could just be else unless you're trying to cover the other states (X,U...) but you would still want an else to cover those.
count = 3 is clearer than count >= 3. count is a 2-bit vector, so it can never be greater than 3.
Although you output 0 when LOAD is asserted while in the SHIFT state, you don't actually load a new value. Did you intend to?
Changing count to a variable without changing the position of the assignments will cause your first X -> output sequence to abort a cycle early (you increment count before you test it against 3). It will cause subsequent X -> output sequences to go "X(3), X(0), X(1), X(2)"
The variable temp is never used. The variable data would work just as well as a signal. You do not need the properties of variables for this use. This also brings up the question of why you tried count as variable; unless you need the instant assignments of variables, it is typically better to use a signal because signals are easier to view in (most) simulators and harder to make mistakes with. I hope that you aren't trying to end up with count as a variable, but just have an academic curiosity why it doesn't work.
Have you looked at this in a simulator? Are you changing states properly? Are all the bits of all your inputs strongly driven to a defined value ('1' or '0')?
I don't see anything that would cause the failure you described merely from changing count to a variable from a signal, but the change would cause the undesired behavior described above. My best guess is that your symptom arises from an issue with how you drive your inputs.

Related

Multiplier via Repeated Addition

I need to create a 4 bit multiplier as a part of a 4-bit ALU in VHDL code, however the requirement is that we have to use repeated addition, meaning if A is one of the four bit number and B is the other 4 bit number, we would have to add A + A + A..., B number of times. I understand this requires either a for loop or a while loop while also having a temp variable to store the values, but my code just doesn't seem to be working and I just don't really understand how the functionality of it would work.
PR and T are temporary buffer standard logic vectors and A and B are the two input 4 bit numbers and C and D are the output values, but the loop just doesn't seem to work. I don't understand how to loop it so it keeps adding the A bit B number of times and thus do the multiplication of A * B.
WHEN "010" =>
PR <= "00000000";
T <= "0000";
WHILE(T < B)LOOP
PR <= PR + A;
T <= T + 1;
END LOOP;
C <= PR(3 downto 0);
D <= PR(7 downto 4);
This will never work, because when a line with a signal assignment (<=) like this one:
PR <= PR + A;
is executed, the target of the signal assignment (PR in this case) is not updated immediately; instead an event (a future change) is scheduled. When is this event (change) actioned? When all processes have suspended (reached wait statements or end process statements).
So, your loop:
WHILE(T < B)LOOP
PR <= PR + A;
T <= T + 1;
END LOOP;
just schedules more and more events on PR and T, but these events never get actioned because the process is still executing. There is more information here.
So, what's the solution to your problem? Well, it depends what hardware you are trying to achieve. Are you trying to achieve a block of combinational logic? Or sequential? (where the multiply takes multiple clock cycles)
I advise you to try not to think in terms of "temporary variables", "for loops" and "while loops". These are software constructions that can be useful, but ultimately you are designing a piece of hardware. You need to try to think about what physical pieces of hardware can be connected together to achieve your design, then how you might describe them using VHDL. This is difficult at first.
You should provide more information about what exactly you want to achieve (and on what kind of hardware) to increase the probability of getting a good answer.
You don't mention whether your multiplier needs to operate on signed or unsigned inputs. Let's assume signed, because that's a bit harder.
As has been noted, this whole exercise makes little sense if implemented combinationally, so let's assume you want a clocked (sequential) implementation.
You also don't mention how often you expect new inputs to arrive. This makes a big difference in the implementation. I don't think either one is necessarily more difficult to write than the other, but if you expect frequent inputs (e.g. every clock cycle), then you need a pipelined implementation (which uses more hardware). If you expect infrequent inputs (e.g. every 16 or more clock cycles) then a cheaper serial implementation should be used.
Let's assume you want a serial implementation, then I would start somewhere along these lines:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity loopy_mult is
generic(
g_a_bits : positive := 4;
g_b_bits : positive := 4
);
port(
clk : in std_logic;
srst : in std_logic;
-- Input
in_valid : in std_logic;
in_a : in signed(g_a_bits-1 downto 0);
in_b : in signed(g_b_bits-1 downto 0);
-- Output
out_valid : out std_logic;
out_ab : out signed(g_a_bits+g_b_bits-1 downto 0)
);
end loopy_mult;
architecture rtl of loopy_mult is
signal a : signed(g_a_bits-1 downto 0);
signal b_sign : std_logic;
signal countdown : unsigned(g_b_bits-1 downto 0);
signal sum : signed(g_a_bits+g_b_bits-1 downto 0);
begin
mult_proc : process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
out_valid <= '0';
countdown <= (others => '0');
else
if in_valid = '1' then -- (Initialize)
-- Record the value of A and sign of B for later
a <= in_a;
b_sign <= in_b(g_b_bits-1);
-- Initialize countdown
if in_b(g_b_bits-1) = '0' then
-- Input B is positive
countdown <= unsigned(in_b);
else
-- Input B is negative
countdown <= unsigned(-in_b);
end if;
-- Initialize sum
sum <= (others => '0');
-- Set the output valid flag if we're already finished (B=0)
if in_b = 0 then
out_valid <= '1';
else
out_valid <= '0';
end if;
elsif countdown > 0 then -- (Loop)
-- Let's assume the target is an FPGA with efficient add/sub
if b_sign = '0' then
sum <= sum + a;
else
sum <= sum - a;
end if;
-- Set the output valid flag when we get to the last loop
if countdown = 1 then
out_valid <= '1';
else
out_valid <= '0';
end if;
-- Decrement countdown
countdown <= countdown - 1;
else
-- (Idle)
out_valid <= '0';
end if;
end if;
end if;
end process mult_proc;
-- Output
out_ab <= sum;
end rtl;
This is not immensely efficient, but is intended to be relatively easy to read and understand. There are many, many improvements you could make depending on your requirements.

Blocking Assignments on SIGNALS in VHDL

I am making an FSM with VHDL. The simplest possible when valid = 1 change from stateA to stateB.
The confusing part is the rising edge selected by the blue rectangular. When valid = '1'. At the first rising edge, the state will be calculated to be B but it won't take effect until the next rising edge BUT what happened that it took effect at the FIRST rising edge.
Because the change in the state from A to B should affect other parts ( parallel process ) in the design in the NEXT cycle. From the waveform, If valid = '1' just before CLK_1.
At, CLK_1 all other processes should see state = A | waveform correct
output
state = A
enteredlastcycle = 0
At, CLK_2 all processes start seeing state = B. another parallel
process checks if state = B then it drives ENTERED_STATEB_LASTCYCLE to
be 1 waveform correct output
state = B
enteredlastcycle = 0
Then at CLK_3, waveform correct output
state = B
enteredlastcycle = 1
Do I misunderstand something?
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.KDlib.all;
entity nearestPoint is
generic ( ARRAY_WIDTH : integer := 8);
port (
clk: in std_logic;
reset: in std_logic;
inpoint: in kdvector;
valid: in std_logic;
finished: buffer std_logic
);
end nearestPoint;
architecture behave of nearestPoint is
signal state: two_state_type;
signal stateB_entered_lastCycle: std_logic;
begin
process ( clk )
begin
if ( reset = '1' ) then
elsif ( rising_edge(clk) ) then
case state is
when stateA =>
if ( valid = '1' ) then
state <= stateB;
end if;
when stateB =>
when others =>
end case;
end if;
end process;
process(clk)
begin
if ( reset = '1' ) then
elsif ( clk = '1' ) then
case state is
when stateA =>
when stateB =>
stateB_entered_lastCycle <= '1';
when others =>
end case;
end if;
end process;
end behave;
I will give you an explanation through a digital circuit prism. It is a way of thinking that you have to keep in mind when you develop VHDL.
Your valid is at 1 before the clock edge. You are in simulation so you can imagine that all your computations are instant. At the input of your flipflop the new value of your state is already calculated.
I am used to code with only one sequential process and one or more combinational process. Maybe you will understand better with this code with same functionnality than yours (a bit simplified) :
SEQ : process(clk, rst)
begin
if rst = '1' then
current_state <= '0';
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process SEQ;
Circuit corresponding to this code :
COMB : process(current_state, valid)
begin
next_state <= current_state; -- Default value to ensure that next_state will always be affected
if current_state = '0' and valid = '1' then
next_state <= '1';
end if;
end process COMB;
Circuit correspondint to this code :
If we consider that when valid changes next_state is refreshed instant, current_state (state in your code) goes high on the very next clock rising edge.
Hope you will understand, if you need more precision, don't hesitate to ask, I can edit my post or answer in comments.
Important note : If you have an asynchronous reset in your sequential process, it has to be in sensitivity list.
VHDL has no concept of blocking/non-blocking assignments. There are signals and variables and they are assigned differently.
In your case, you need to remember that simulation runs on a series of delta cycles. 1 delta is an infinitely small space of time, but they happen sequentially. A signal assignment doesn't take effect until the end of the delta, so state = B in the delta cycle after the rising edge of the clock. The 2nd process is sensitive only the clock, so it cannot update stateB_entered_lastcycle until the clock rises again.

Edit - Can't Infer Register Because It's Behavior Does Not Match Any Supported Register Model VHDL

This is a branch off of a separate question I asked. I am going to explain more in depth on what I am trying to do and what it is not liking. This is a school project and doesn't need to follow standards.
I am attempting to make the SIMON game. Right now, what I am trying to do is use a switch case for levels and each level is supposed to be faster (hence different frequency dividers). The first level is supposed to be the first frequency and a pattern of LEDs is supposed to light up and disappear. Before I put in a switch case, the first level was by itself (no second level stuff) and it lit up and disappeared like it should. I also used compare = 0 in order to compare in output to an input. (The user is supposed to flip up the switches in the light pattern they saw). This worked when the first level was by itself but now that it is in a switch case, it doesn't like compare. I'm not sure how to get around that in order to compare an output to an input.
The errors I am getting are similar to before:
Error (10821): HDL error at FP.vhd(75): can't infer register for "compare" because its behavior does not match any supported register model
Error (10821): HDL error at FP.vhd(75): can't infer register for "count[0]" because its behavior does not match any supported register model
Error (10821): HDL error at FP.vhd(75): can't infer register for "count[1]" because its behavior does not match any supported register model
Error (10821): HDL error at FP.vhd(75): can't infer register for "count[2]" because its behavior does not match any supported register model
Error (10822): HDL error at FP.vhd(80): couldn't implement registers for assignments on this clock edge
Error (10822): HDL error at FP.vhd(102): couldn't implement registers for assignments on this clock edge
Error (12153): Can't elaborate top-level user hierarchy
I also understand that it doesn't like the rising_edge(toggle) but I need that in order to make the LED pattern light up and disappear.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity FP is
port(
clk, reset : in std_logic;
QF : out std_logic_vector (3 downto 0);
checkbtn : in std_logic;
Switch : in std_logic_vector(3 downto 0);
sel : in std_logic_vector (1 downto 0);
score : out std_logic_vector (6 downto 0)
);
end FP;
architecture behavior of FP is
signal time_count: integer:=0;
signal toggle : std_logic;
signal toggle1 : std_logic;
signal count : std_logic_vector (2 downto 0);
signal seg : std_logic_vector (3 downto 0);
signal compare : integer range 0 to 1:=0;
type STATE_TYPE is (level1, level2);
signal level : STATE_TYPE;
--signal input : std_logic_vector (3 downto 0);
--signal sev : std_logic_vector (6 downto 0);
begin
process (clk, reset, sel)
begin
if (reset = '0') then
time_count <= 0;
toggle <= '0';
elsif rising_edge (clk) then
case sel is
when "00" =>
if (time_count = 1249999) then
toggle <= not toggle;
time_count <= 0;
else
time_count <= time_count+1;
end if;
when "01" =>
if (time_count = 2499999) then
toggle1 <= not toggle1;
time_count <= 0;
else
time_count <= time_count+1;
end if;
when "10" =>
if (time_count = 4999999) then
toggle <= not toggle;
time_count <= 0;
else
time_count <= time_count+1;
end if;
when "11" =>
if (time_count = 12499999) then
toggle <= not toggle;
time_count <= 0;
else
time_count <= time_count+1;
end if;
end case;
end if;
end process;
Process (toggle, compare, switch)
begin
case level is
when level1 =>
if sel = "00" then
count <= "001";
seg <= "1000";
elsif (rising_edge (toggle)) then
count <= "001";
compare <= 0;
if (count = "001") then
count <= "000";
else
count <= "000";
end if;
end if;
if (switch = "1000") and (compare = 0) and (checkbtn <= '0') then
score <= "1111001";
level <= level2;
else
score <= "1000000";
level <= level1;
end if;
when level2 =>
if sel = "01" then
count <= "010";
seg <= "0100";
elsif (rising_edge (toggle1)) then
count <= "010";
compare <= 1;
if (count = "010") then
count <= "000";
else
count <= "000";
end if;
end if;
if (switch = "0100") and (compare = 1) and (checkbtn <= '0') then
score <= "0100100";
else
score <= "1000000";
level <= level1;
end if;
end case;
case count is
when "000"=>seg<="0000";
when "001"=>seg<="1000";
when "010"=>seg<="0100";
when "011"=>seg<="0110";
when "100"=>seg<="0011";
when others=>seg<="0000";
end case;
end process;
QF <= seg;
end behavior;
Thanks again in advance!
Well... it is hard to tell what is wrong, because this state machine is written in wrong way. You should look for references about proper modeling of FSM in VHDL. One good example is here.
If you use Quartus, you could also look for Altera's description on how to model FSM specifically for their compiler.
I will now give you just two advices. First is that you shouldn't (or mabye even you can't) use is two
if rising_edge (clk)
checks in one process. If your process is supposed to be sensitive on clock edge, write it once at the beginning.
Second thing is that if you want to model FSM with one process with synchronous reset, then put just clk on sensitivity list.
EDIT after question and code edit:
Ok, much better now. But another few things:
Your FSM is still not like it should. Look again at the example in the source I gave you above and edit it to be like there, or make it one process FSM like in example in this link.
Intends! Very important. I couldn't spot some of obvious errors, before I made proper intendation in your code. This leads me to...
Look at the places, there you assign values to count, in particular the if statements. No mater what, you assign the same value of "000".
Similar story with another signal - seg. You assign to it some value in the process, and then at the end of this process there is case statement in which you assign to it some other value, making this previous assignments irrelevant.
Use rising_edge only once in the process, only to clock, and only at the very beginning of the process, or in the way you did in the first process, that has asynchronous reset. In second process you did all this three things.
In sequential process with rising_edge, like the first one, you don't have to put to sensitivity list anything more than clock, and reset if it is asynchronous, like in your case.
Sensitivity list in second process. It is parallel process, so you should put there signals, that you check in a process, and can change outside of it. It is not the case for compare. But there should be signals: level, sel and toggle1.
As I'm still not sure what are you trying to achieve, I will not tell you what exactly to do. Fix your code according to points above, then maybe it will just work.

How to specify these conditions in my counter

I had a problem with synthesizing my code with using ISE. Please check the code and give me a suggestion how to modify it with need of a specific condition. My problem is only with the STAYCOUNT entity of a counter. Note that clk is feeding by another circuit and staycount is also feeding by another circuits.
at the initialization step, STAYCOUNT = 0, and if Reset = 0 , and the clk = 1 then count=count+1, and give an output DOUT = COUNT.
if reset = 1 then count = count - count.
then the next circuit process the output of DOUT, and it will either stop feeding the counter or feeding it (staycount = 1) in a specific condition.
whenever staycount = 1.
if clk = 1 then
while staycount = 1 loop
count = count + 1
DOUT <= count
end loop
end if
there are 2 problems: 1. at the initialization step only if staycount = 0 and clk= 1 it should only process count=count+ 1 for only 1 time and give an output DOUT.
After DOUT send a signal to another circuit, this circuit has 2 output either staycount which is going to be equal to 1 or proceed to for another output.
2. suppose that the other circuit give an output staycount = 1, it should feed the counter, and the counter again will check if the clk= 1 and the staycount= 1 to make count=count + 1 and give another output DOUT = COUNT.
please check my code for the counter. However, it missed the statement of problem#1, and succeeded in problem# 2, but with error Xilinx ISE "Non-static loop limit exceeded".
entity counter is
generic(n: natural :=4);
port( CLK: in std_logic;
Reset : in std_logic;
staycount: in std_logic;
DOUT : out std_logic_vector(n-1 downto 0) );
end counter;
architecture behavior of counter is
begin
process(CLK,CLK,Reset,staycount,COUNT) -- behavior describe the counter
variable COUNT:std_logic_vector(n-1 downto 0);
begin
if Reset = '1' then
COUNT := COUNT - COUNT;
elsif (CLK='1' and CLK'event) then
while (staycount = '1') loop
COUNT := COUNT + 1;
DOUT <= COUNT after 50 ns;
end loop;
else DOUT <= COUNT;
end if;
end process;
end behavior;
Make count a register
It looks like you are using count to keep the state of your design. It is neater, and often easier to debug, to make it a signal - which becomes a register if you assign it on clock edges.
Declare count as a signal in the architecture instead of as a variable, and assign it its next value at every clock edge. I also recommend resetting, in the process, to zeros instead of subtracting by itself - otherwise you may end up with propagating uninitialized values in your implementation.
if reset = '1' then
count <= (others => '0');
elsif (CLK='1' and CLK'event) then
count <= count_n;
end if;
Assign the count_n signal concurrently, being mindful of that you always want to increment it at least once:
count_n <= (n-1 downto 1 => '0') & '1' when count = 0 else
count when staycount = '0' else
count + 1;
Now also assign your output concurrently based on the count signal, and note that you can limit your sensitivity list to only clk and reset.

State Machine with VHDL for UA(R)T

I am trying to create a state machine in vhdl for UA(R)T (Only the sending portion).
I am having an issue with the flow of the program. I know the buad rate portion does not work at the moment. I am trying to get it working with just a clock at the moment, and then will implement the baud rate divider.
When I run it through my test bench (nothing complicated, just assign a couple of initial values reset = 1 for x time, din = z, baud = y, etc), nothing happens. My output txd stays at the initial '1' value that is set in the reset stage and if I set it to '0' it will stay like that for the cycles.
My issue that I had when designing the state machine is the it has two values that it will transition on BUT not in ever state.
Basically, what it is supposed to do is:
reset: txd = 1, count = 1, busy = 0, we = 0
idle: when busy = 1 set shift = init values
wait: transition on next clock signal
trans: if count < 9, txd = shift(0), and shift shift
if count = 9, busy = 0, count = 0
and back to idle
I think my issue is somehow related to the busy signal not being properly set.
-- Universal Asynch Receiver Transmitter
---------------------
library ieee;
use ieee.std_logic_1164.all;
entity eds_uart is
generic (width : positive := 16);
port ( clk,reset: in std_logic ;
din_wen: buffer std_logic; -- state machine sets value thus buffer needed
brd : in std_logic_vector(23 downto 0); -- buad rate dividor
din : in std_logic_vector(7 downto 0); -- input value
txd: out std_logic; -- sent data bit
tx_busy : buffer std_logic -- sent data bit active
);
end entity eds_uart;
architecture behaviour of eds_uart is
type state_type is (idle_s, wait_s, transmit_s); -- three possible states of uat
signal current_s: state_type;
signal tick: std_logic; -- baud rate clock
signal count: integer := 0; -- count number of characters sent
signal shift: std_logic_vector(9 downto 0); -- intermediate vector to be shifted
begin
-- assign tick value based on baud rate
-- need to implement divisor
process(clk, brd) begin
tick <= clk;
end process;
process(tick, reset, din) begin
if (reset = '1') then
current_s <= idle_s; -- default state
count <= 0; -- reset character counter
txd <= '1';
tx_busy <= '0';
din_wen <= '0'; -- able to start sending
elsif (current_s = idle_s and din_wen = '1') then -- transition when write enable is high
current_s <= wait_s; -- transition
tx_busy <= '1';
shift <= '1' & din & '0'; -- init shift value
elsif (current_s = wait_s and rising_edge(tick)) then -- transition on clock signal
current_s <= transmit_s;
elsif (current_s = transmit_s and rising_edge(tick)) then -- test transition on clock signal
if (count < 9) then
txd <= shift(0); -- output value
shift <= '0' & shift(9 downto 1); -- shift to next value
count <= count + 1; -- increment counter
current_s <= transmit_s; -- dont change state
elsif (count = 9) then
txd <= shift(0); -- send last element
count <= 0;
tx_busy <= '0'; -- reset busy signal
current_s <= idle_s; -- start process again
end if;
end if;
end process;
end architecture behaviour ;
The comments:
-- state machine sets value thus buffer needed
and
-- transition when write enable is high
suggest that you may be expecting to have an additional external driver for din_wen. If that is the case the buffer mode is not doing you any good as it only exposes the value of the internal driver of din_wen which is only ever driving '0'. Post VHDL-2002, buffer is effectively a fancy, readable version of out without the limitations from earlier standards. It does not implement an input port. More significantly, it does not let you see the external resolved value if you have additional signal driver(s) outside this entity.
It isn't clear why you even need to drive din_wen internally since it is intended to be a control input that causes the transition into the wait_s state. Consider changing it to an in port mode and removing the reset assignment.
Style note: You are courting danger with the mixture of synchronous and asynchronous logic described here. You should stick to the pattern of having a single call to rising_edge() in a top level if block that wraps all of your synchronous logic.

Resources