I'm having "Iteration limit reached" error in a simple FSM.
This is a part of of a bigger FSM I have to do for a class assignment, and I tracked the problem to this specific part.
The FSM will be controlling a counter, the state IDLE waits for inputs, ZERO sets the counter to zero, and the INCREMENT state increments the counter by one.
When simulating, the error occurs at the first time the input "inc" is high and the clock rises.
If I change the statement "temp := temp + 1;" for "temp := anything" the error stops. I really don't know what can be wrong, as for what I have found this error occurs when changing signals in the process sensitivity list inside the process itself.
I'm using Quartus II for the simulation.
Sorry for english mistakes.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.all;
entity fsm is
port
(
clock: in std_logic;
reset: in std_logic;
inc: in std_logic;
count: out std_logic_vector (13 downto 0);
cur_state: out std_logic_vector (1 downto 0)
);
end fsm;
architecture behaviour of fsm is
type state_type is (IDLE, INCREMENT, ZERO);
signal PS, NS: state_type;
begin
sync_proc: process (clock, reset)
begin
if (reset = '1') then
PS <= ZERO;
elsif (rising_edge(clock)) then
PS <= NS;
end if;
end process sync_proc;
comb_proc: process (PS, inc)
variable temp: unsigned (13 downto 0);
begin
case PS is
when IDLE =>
if (inc = '1') then
NS <= INCREMENT;
else
NS <= IDLE;
end if;
when INCREMENT =>
temp := temp + 1;
NS <= IDLE;
when ZERO =>
temp := "00000000000000";
NS <= IDLE;
when others =>
NS <= IDLE;
end case;
count <= std_logic_vector(temp);
end process comb_proc;
with PS select
cur_state <= "00" when IDLE,
"01" when INCREMENT,
"10" when ZERO,
"11" when others;
end behaviour;
You have a very serious CONCEPTUAL mistake in your case statement. Because it produces a combinational circuit (the combinational part of your FSM), it does not have memory, so it can't implement the equation "temp := temp + 1" (because, having no memory, it doesn't know what the value of temp is).
You can see more about this in chapter 11 of "Finite State Machines in Hardware...", by V.Pedroni, published by MIT.
Related
I will take two 1024-bit unsigned integers through serial communication ( 8-bit by 8-bit), convert ASCII to binary, then multiply them to form an output of 2048-bit. The main problem that I have to do multiplication operation with a very small-area FPGA board ( BASYS 2).
The multiplication speed is not an important criteria for me, I can wait a relatively long time ( ~ 1 sec ) to get the correct multiplication result.
Here is the resources information of my FPGA:
https://reference.digilentinc.com/_media/basys3:basys3_ss.pdf
What is a simple and area-effective way to do this?
a 1024-bit to 1024-bit adder takes alone around %53 of my area usage!
I assume you are certain that a true 1024 x 1024 multiplier really is needed (in many applications, something much cheaper will suffice). Maybe this is stating the obvious, but as a starting point I would try a very simple shift-add. Something like this would work (and I'm sure you can optimize it further to meet your needs):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity wide_mult is
generic (
A_BITS : positive := 1024;
B_BITS : positive := 1024
);
port (
clk : in std_logic;
-- Input
in_valid : in std_logic;
in_a : in unsigned(A_BITS-1 downto 0);
in_b : in unsigned(B_BITS-1 downto 0);
-- Output
out_valid : out std_logic;
out_prod : out unsigned(A_BITS+B_BITS-1 downto 0)
);
end wide_mult;
architecture rtl of wide_mult is
signal shifted_a : unsigned(A_BITS-1 downto 0);
signal shifted_b : unsigned(A_BITS+B_BITS-1 downto 0);
signal progress : std_logic_vector(A_BITS-1 downto 0);
signal sum : unsigned(A_BITS+B_BITS-1 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
-- Cycle 1
if in_valid = '1' then
-- Initialize
shifted_a <= in_a;
shifted_b <= resize(in_b, A_BITS+B_BITS);
progress <= std_logic_vector(to_unsigned(1, A_BITS));
else
-- Shift
shifted_a <= shift_right(shifted_a, 1);
shifted_b <= shift_left(shifted_b, 1);
progress <= progress(A_BITS-2 downto 0) & '0';
end if;
-- Cycle 2 - Accumulate sum
out_valid <= progress(A_BITS-1);
if progress(0) = '1' then
-- Init sum
if shifted_a(0) = '0' then
sum <= (others => '0');
else
sum <= shifted_b;
end if;
elsif shifted_a(0) = '1' then
-- Accumulate
sum <= sum + shifted_b;
end if;
end if;
end process;
out_prod <= sum;
end rtl;
Your device is very small. If the simple shift-add doesn't even get close to fitting, then this might indicate that you need to change your approach. Since you have an enormous amount of time to do this sum, then perhaps you could offload it to a nearby CPU?
So I am designing a serial squarer. My program takes a basic binary counter, and uses each count of the counter to calculate squares in series. When I try to synthesize my code, depending on how I arrange my code, either synthesis runs almost infinitely, or the synthesis run just crashes entirely. So I figured that I cannot update my signal r_final => r_final + r_min1 because I remember that not being a thing in vhdl. So I have decided that I need to set r_final to a variable instead of a signal. I'm not sure how I should declare r_final as a variable. Can anyone provide some insight on how I can get r_final to update with itself?
This is my main code, the part in question is under the comment -- next state logic:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity serial_square is
port(
clk, reset: in std_logic;
q: out std_logic_vector (3 downto 0));
end serial_square;
architecture behavioral of serial_square is
signal r_reg : unsigned (3 downto 0) := "0000";
signal r_next : unsigned (3 downto 0);
signal r_2i : unsigned (3 downto 0);
signal r_min1 : unsigned (3 downto 0);
shared variable r_final : unsigned := "0000";
begin
-- register
process(clk,reset)
begin
if (reset='1') then
r_reg <= (others => '1');
elsif (clk'event and clk='1') then
r_reg <= r_final;
end if;
end process;
-- next state logic
r_next <= r_reg +1; -- r_reg + 1
r_2i <= r_next(2 downto 0) & '0'; -- multiply by 2
r_min1 <= r_2i - 1; -- minus one
r_final := r_min1 + r_final; -- add r_min1 to r_final, output should be the count r_next, squared.
--output logic
q <= std_logic_vector(r_reg);
end behavioral;
The update of r_final must be in the clocked process, so the next value is generated through a synchronous (clocked) update, since this is the structure that matches the available hardware.
Shared variables can't be synthesized, but is a feature only used for test benches.
I am trying to build a generic baud rate generator process for a uart transmitter.
The transmitter works fine if I ignore the baud rate divider and pass in the clk signal in the sensitivity list. But I get errors (describe in code comments) if I try to implement the divider. I tried two different methods and both either gave an error, or did not have the expected output. Yes, the exact code posted will not work since I assign fbaud twice, I comment one out to test.
Perhaps I don't understand how the baud generator is supposed to work. From my understanding, the fpga clock runs at 50mHz which is to fast for the rs232 communication. So we need to wait a certain number of clock cycles before we can transmit our character.
In this case, we have a variable baud so we divide the stock clock by the baud generator to get the number of clock cycles we need to wait before sending our 'tick' signal to the transmit state machine.
The baud divider is set in the test bench to x"000008".
-- Universal Asynch Receiver Transmitter
---------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity eds_uart is
generic (width : positive := 16);
port ( clk,reset: in std_logic ;
din_wen: in 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 := '0'; -- 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
signal fbaud: integer := 0;
signal fbaud_counter: integer := 0;
begin
--- process that is causing the issue.
process(clk, brd) begin
fbaud <= (50000000)/to_integer(signed(brd)); -- 50,000,000 is the default clock Hz
------ error message ------
--# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
-- # Time: 0 ns Iteration: 0 Instance: /eds_uart_tb/inst_uart
-- # ** Fatal: (SIGFPE) Floating point exception.
--# Time: 0 ns Iteration: 0 Process: /eds_uart_tb/inst_uart/line__29 File:
fbaud <= 50000;
--- error ---
-- this command simply does not work, it compiles and runs though
-- I don't get any transitions in my output wave
-- I don't think it is entering the transmit stage based on a clock signal
if (rising_edge(clk)) then
if (fbaud_counter = fbaud) then -- tick when proper number of counts have appeared
tick <= '1';
elsif (fbaud_counter < fbaud) then
tick <= '0';
fbaud_counter <= fbaud_counter + 1;
end if;
end if;
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';
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
end if;
if(rising_edge(tick)) then
if (current_s = wait_s) then -- transition on clock signal
current_s <= transmit_s;
elsif (current_s = transmit_s) then -- 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 if;
end process;
end architecture behaviour ;
There are a few potential problems with this code, but what seems to be causing your failure is that you're declaring fbaud_counter as an integer but with no range limit specified, and more critically, you're not clearing it when it reached your fbaud count value. Since you never reset the value after the count is reached, it will continue counting through all 2^32 values before it wraps around and matches fbaud again. A range limit is probably a good idea anyway, but either way, if you don't reset it, your baud rate will not be correct. For instance:
if (rising_edge(clk)) then
if (fbaud_counter = fbaud - 1) then
tick <= '1';
fbaud_counter <= 0;
else
tick <= '0';
fbaud_counter <= fbaud_counter + 1;
end if;
end if;
Note that there's really no need for an elsif condition there, as there really isn't a condition where you don't otherwise want to set tick to '0' or increment your count. Note that I'm also counting to fbaud - 1 - If you start at 0, counting all the way to fbaud may put your rate off very slightly.
edit
I simulated the above with the changes I recommended to the process, and I got a response on txd (as well as a steady tick). Are you sure you're simulating long enough? Assuming your clock is set up to be 50 MHz as your code indicates it should be, setting brd to x"000008" will give you an incredibly slow tick rate (8 Hz, oddly enough). I reduced the numerator to 5000 just to speed things up a bit.
I also realize I didn't cover your floating point exception (thanks for pointing that out).
The warning is a hint as to the error. "metavalue detected, returning 0". The warning indicates to_integer is trying to convert a value that it can't resolve to a 1 or 0 (e.g. 'X', or another such std_logic value), and of course you can't divide by 0. This is most likely an initialization problem (note that your fatal error says Time: 0 ns Iteration: 0). In your testbench, how is brd driven initially? Can you give it a default value? If not, you will need to guard against this condition some other way.
When you simulate it it sounds like your brd input is not initialized, so the Us are turning into 0s and you are dividing by zero - hence the exception.
Also, this will synthesise to something very big, resource-wise:
fbaud <= (50000000)/to_integer(signed(brd));
You are asking for this to be calculated every clock cycle, which is a big ask from the hardware.
The usual method is to accept a terminal count (your fbaud) as the input and let the controlling software figure out what the value should be. Or calculate it at compile time as a constant, depending on how flexible you need to be.
I have made this program in VHDL, alle syntax's are fine, and I have tried to double check all the port maps, but I get some warnings that causes the program not to work, even tough it can generate the bit file.. anybody here who can help please??
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity topMain is
port( clk : in std_logic;
alarm : in std_logic_vector (1 downto 0);
d_open : in std_logic_vector (1 downto 0);
d_closed : in std_logic_vector(1 downto 0);
d_out : out std_logic_vector (1 downto 0));
end topMain;
architecture Behavioral of topMain is
type state_type is (S0,S1,S3);
signal NS, Current_State : state_type;
begin
process (clk, alarm)
begin
if alarm ="11" then
Current_State <= S3; --
elsif rising_edge (clk) then
Current_State <= NS; -- state change
end if;
end process;
--------------------------------
process(Current_State,d_open, d_closed, clk)
begin
case Current_State is
----
when S3 => d_out <= "11";
if (d_open = "10") then
NS <= S3;
elsif (d_closed = "01") then
NS <= S3;
elsif (d_closed = "00") then
NS <= S3;
end if;
----
when S0 => d_out <= "10"; -- open door
if ( d_open = "10" ) then
NS <= S0;
elsif (d_closed= "01") then
NS <= S1;
elsif (d_closed = "10") then
NS <= S0;
else
NS <= S0;
end if;
when S1 => d_out <= "01"; -- open door
if ( d_closed = "01" ) then
NS <= S1;
elsif (d_open <= "10") then
NS <= S0;
elsif (d_open <= "01") then
NS <= S1;
else
NS <= S1;
end if;
end case;
end process;
end Behavioral;
And in case anybody can take a look at it, this is the full project.
Its a simple program containg a finite state machine with 3 changes, simulating a burglar alarm.
When alarm is off, you can open door and close it, but if its on, you cant do anything. at lease thats what i was trying to make, altough i am newbie. Please forgive me for any inconvenience it may cause you.
http://www.abmy.dk/BAlarm.zip
The warnings I am getting right now:
WARNING:Xst:819 - "C:/Xilinx/OP/BAlarm/topMain.vhd" line 36: One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:
WARNING:Xst:737 - Found 3-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:647 - Input is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:PhysDesignRules:372 - Gated clock. Clock net top/NS_not0001 is sourced
by a combinatorial pin. This is not good design practice. Use the CE pin to
control the loading of data into the flip-flop.
WARNING:Route:455 - CLK Net:top/NS_not0001 may have excessive skew because
The NS signal is not assigned in all branches of the combinatorial process
process(Current_State, d_open, d_closed, clk), which will infer latches; see also https://stackoverflow.com/a/20394822/2352082 and https://stackoverflow.com/a/20411227/2352082
The code:
when S3 => d_out <= "11";
if (d_open = "10") then
ns <= S3;
elsif (d_closed = "01") then
ns <= S3;
elsif (d_closed = "00") then
ns <= S3;
end if;
does not have an else, so if neither of the previous conditions
are TRUE, then NS is not assigned, which results in a latch inferred by
synthesis.
You may fix this by adding an else with proper assign NS value assign, like:
...
else
ns <= S0; -- TBD[S0 is only example; use correct value]
end if;
I don't see any signals missing in the process sensitivity list, but clk is
included and not required in the last one, since this process implements combinatorial design.
I'm still trying to get used to some of the quirks of VHDL and I'm having a bit of an issue. First off, I understand that shift operators like rol, ror, ssl, srl, etc. are not synthesizeable. The purpose of this lab is to use a golden model to check against a synthesizeable version of the same thing in a testbench.
Now, the purpose of this program is to convert thermometer code into a 3-bit binary number. So, in other words, thermometer code "00000001" = "001", "00000011" = "010", "00000111" = "011", etc. I'm basically trying to count the number of 1's in the string from right to left. There will be no case where a '0' is placed between the string of 1's, so the vector "00011101" is invalid and will never occur.
I've devised a non-synthesizeable (and so far, non-compile-able) algorithm that I can't figure out how to get working. Basically, the idea is to read the thermometer code, shift it right and increment a counter until the thermometer code equals zero, and then assign the counter value to the 3-bit std_logic_vector. Below is the code I've done so-far.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity therm2bin_g is
port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
bin : out std_logic_vector(2 downto 0); -- binary code
i : integer range 0 to 7);
end therm2bin_g;
architecture behavioral_g of therm2bin_g is
begin
golden : process(therm)
begin
while(therm /= "00000000") loop
therm <= therm srl 1;
i = i + 1;
end loop;
bin <= std_logic'(to_unsigned(i,3));
end process golden;
behavioral_g;
here's a version that is synthesisable. the while loop is replaced by a for loop. srl is implemented explicitly:
entity therm2bin_g is
port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
bin : out std_logic_vector(2 downto 0); -- binary code
i : out integer range 0 to 7);
end therm2bin_g;
architecture behavioral_g of therm2bin_g is
begin
golden : process(therm)
variable i_internal: integer range 0 to 7;
begin
i_internal:=0;
for idx in 0 to therm'length loop
if therm/="0000000" then
therm<='0' & therm(therm'left downto 1);
i_internal := i_internal + 1;
end if;
end loop;
bin<=std_logic_vector(to_unsigned(i_internal,bin'length));
i<=i_internal;
end process golden;
end behavioral_g;
"... operators like rol, ror, ssl, srl, etc. are not synthesizeable..."
Who says that on who's authority? Have you checked? On which synthesis tool? Was it a recent version, or a version from the early 1990s?
Note that the argument that some tools might not support it is just silly. The fact that some kitchens might not have an oven does not stop people from writing recipes for cake.