I am developing a 8 bit unsigned prime number detector in VHDL, synthesizable, for a project.The objective is to do not only avoiding to use any sort of loops or latches as well as restricting it to only the FPGA 50Mhz clock.
We tried a clock-based using successive divisions but such implementation does not meet the timing requirements in Quartus Timequest when we try to output the result.
When we comment the output it seems to work just fine, and we don't fully understand the why.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity primeChecker is
generic(NumCyclesWait :integer := 1000);
port( clock: in std_logic;
enable: in std_logic;
reset : in std_logic;
input : in std_logic_vector(7 downto 0);
output : out std_logic_vector(7 downto 0);
isPrime : out std_logic_vector(0 downto 0));
end primeChecker;
architecture arch of primeChecker is
signal count: integer := 0;
signal numToCheck : integer := 0;
signal prime, primeOut : integer := 1;
signal s_out: unsigned(7 downto 0);
signal div : integer := 2;
signal clockCount : unsigned(0 downto 0) := "0";
begin
numToCheck <= to_integer(unsigned(input));
process(clock)
begin
if(rising_edge(clock)) then
if(count = NumCyclesWait) then
if ((numToCheck = 1) OR (numToCheck = 0)) then
prime <= 0; --Not Prime
elsif(numToCheck > 2 and prime =1 and div < numToCheck) then
if (numToCheck rem div = 0) then
-- if the number is divisible
prime <= 0;
end if;
div <= div +1;
end if;
else
count <= count +1;
end if;
if(enable = '1') then
s_out <= to_unsigned(numToCheck,8);
count <= 0;
div <= 2;
primeOut <= prime;
prime <= 1;
else
s_out <= s_out;
end if;
end if;
end process;
isPrime <= std_logic_vector(to_unsigned(primeOut,1));
output <= std_logic_vector(s_out);
end arch ; -- arch
I expect for it not to trigger the "Timing requirement not met" error and for it to fully compile.
For fastest constant time response, I would take a different approach. Your task is to deal with eight bit numbers only and your FPGA probably has more than enough RAM to set up an 8-bit prime number lookup table where each table entry just indicates whether its index is a prime number or not:
type prime_numbers_type is array(0 to 255) of std_ulogic;
constant prime_numbers : prime_numbers_type :=
( '0', '0', '1', '1', '0', '1', ... );
This makes the vital part of your prime number detector overly simple:
is_prime <= prime_numbers(to_integer(unsigned(num_to_check)));
I would probably just write a small Tcl script to set up the lookup table.
Related
I am working on implementing a counter component to my vending machine where a user can select 2 items candy 5 cent gum is 10 cent and came across some difficulties with how do I increment a number by 5 or 10 depending on what the user select when I run my code I am getting a runtime error when trying to simulate it also the user can only put up to 30 cent into the machine.
the counter component only keeps track of the amount of nickels or dimes put into the machine such as: 5 cent then another 10 cent the counter will increment to 15
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity count is port(clk,reset,nickel,dime:in std_logic;
totalAmt:out std_logic_vector(3 downto 0));
end count;
architecture beh of count is
signal sum:std_logic_vector(3 downto 0);
signal tmp1: std_logic_vector(3 downto 0) := "0101";
signal tmp2: std_logic_vector(3 downto 0) := "1010";
signal tally: std_logic_vector(3 downto 0);
signal grantot: std_logic_vector(3 downto 0);
begin
process(clk,reset,nickel,dime,sum)
begin
sum <= "0000";
tally <= "0000";
if (reset = '1') then sum <= "0000";
elsif(clk'event and clk = '1') then
elsif(nickel = '1') then sum <= tmp1; -- when nickel or dime is set to one it increments the sume amount by 5 or 10 in binary
elsif(dime = '1') then tally <= tmp2;
end if;
end process;
grantot <= sum + tally;
--if sum >= "11110" then
--report "error";
--else
totalAmt <= grantot;
--end if;
end;
You can't do the math directly on STD_LOGIC_VECTOR signals. You need to declare some sort of math type - I would recommend the type UNSIGNED, which is included in the IEEE.NUMERIC_STD.ALL package that you already include in your code.
You can declare it as follows:
signal sum : UNSIGNED(4 downto 0) := to_unsigned(<your_number>, <signal_width>;
Where <signal_width> would be 5, since you're using 5 bit numbers.
Keep in mind that you'll need to resize your signals after an addition, since the result of an addition of two numbers is wider than the original operands. You do that as follows:
sum <= resize( tmp1 + tmp2, <signal_width>)
Where <signal_width> will be 5, as that's how wide you declared sum. If you don't do the resize, you will likely get an error saying that your target signal isn't wide enough.
I've got two 115bits unsigned vectors. I have to do some mod calculations on them, but Quartus shows those errors.
Error: In lpm_divide megafunction, LPM_WIDTHN must be less than or equals to 64
Error: In lpm_divide megafunction, LPM_WIDTHD must be less than or equal to 64
Error: Can't elaborate inferred hierarchy "lpm_divide:Mod0"
I fully understand, that numbers are too large to perform mod. Is there a way/library/any idea how to solve this problem? I would love to avoid using any "substracting loop", and be as simple as possible. VHDL is not my world, and after academic project I will abandon it with pleasure :P
Application has to calculate modulo inversion. As far as I am not master from VHDL, I've tried doing it using fast powering + mod alghoritm. Application can sucks, it just has to work :d
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
library altera;
use altera.altera_primitives_components.all;
entity inwersja is
port(
a: in unsigned(114 downto 0);
clk: in std_logic;
start: in std_logic;
reset: in std_logic;
c: out unsigned(114 downto 0);
ready: out std_logic);
end inwersja;
architecture i1 of inwersja is
begin
process(clk)
variable tempOutput : unsigned(114 downto 0) := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
variable temp : unsigned (114 downto 0):= a;
variable modul: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011";
variable power: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101001";
variable counter: integer := 0;
begin
if reset='1' then
tempOutput := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
ready <= '0';
elsif clk'event and clk='1' then
if start='0' then
ready<='0';
else
if (counter < 115) then
if (power(counter) /= '0') then
tempOutput := (tempOutput * temp) mod modul;
end if;
temp := (temp * temp) mod modul;
counter := counter + 1;
elsif (counter = 115) then
ready <= '1';
end if;
end if;
end if;
c <= tempOutput;
end process;
end i1;
I'm new to VHDL and am trying to code up Booth's Multiplication Algorithm. I'm using XILINX and when I synthesize my code, I end up with a lot of warnings:
Upper is assigned but never used,
Product is used but never assigned,
LowerPrevLSB is assigned but never used,
Lower is assigned but never used,
A_2sComp is assigned but never used,
Z has a constant value of 0,
Product has a constant value of 0.
I thought I assigned and wrote the code correctly, but evidently I am not. Any advice and help would be appreciated.
library IEEE;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
-- X * Y = Z
entity BoothMultiplier is
generic
(
numBits_X : integer := 8;
numBits_Y : integer := 8
);
port
(
CLK : in std_logic;
X : in std_logic_vector((numBits_X - 1) downto 0);
Y : in std_logic_vector((numBits_Y - 1) downto 0);
Z : out std_logic_vector((numBits_X + numBits_Y - 1) downto 0)
);
end BoothMultiplier;
architecture Behavioral of BoothMultiplier is
-- Two's Complement Function
function TwosComplement(inputNum : std_logic_vector) return std_logic_vector;
function TwosComplement(inputNum : std_logic_vector) return std_logic_vector is
variable temp : std_logic_vector(inputNum'range);
begin
temp := (not inputNum) + 1;
return temp;
end TwosComplement;
-- End Two's Complement Function
-- MIN Function
function MIN(Left, Right : integer) return integer;
function MIN(Left, Right : integer) return integer is
begin
if Left < Right then return Left;
else return Right;
end if;
end Min;
-- End MIN Function
-- MAX Function
function MAX(Left, Right : integer) return integer;
function MAX(Left, Right : integer) return integer is
begin
if Left > Right then return Left;
else return Right;
end if;
end MAX;
-- End MAX Function
-- Signals
signal Upper : std_logic_vector(MAX(numBits_X, numBits_Y) - 1 downto 0)
:= (others => '0');
signal Lower : std_logic_vector(MIN(numBits_X, numBits_Y) - 1 downto 0)
:= (others => '0');
signal LowerPrevLSB : std_logic := '0';
signal Product : std_logic_vector(numBits_X + numBits_Y - 1 downto 0)
:= (others => '0');
signal A, A_2sComp : std_logic_vector(MAX(numBits_X, numBits_y) - 1 downto 0)
:= (others => '0');
signal counter : integer := 0;
-- End Signals
begin
assert Z'length = (X'length + Y'length) report "Bad Product Length" severity failure;
Lower <= X when (numBits_X <= numBits_Y) else Y;
A <= X when (numBits_X > numBits_Y) else Y;
A_2sComp <= TwosComplement(A);
process(CLK)
begin
if rising_edge(CLK) then
if (Lower(0) = '0' and LowerPrevLSB = '1') then
Upper <= Upper + A;
elsif (Lower(0) = '1' and LowerPrevLSB = '0') then
Upper <= Upper + A_2sComp;
end if;
LowerPrevLSB <= Lower(0);
Product <= Upper & Lower;
for i in 0 to Product'length - 2 loop
Product(i) <= Product(i+1);
end loop;
Product(Product'length-1) <= Product(Product'length-1);
Upper <= Product(Product'length - 1 downto MIN(numBits_X, numBits_Y));
Lower <= Product(MIN(numBits_X, numBits_Y) - 1 downto 0);
counter <= counter + 1;
if (counter = MIN(numBits_X, numBits_Y)) then
Z <= Product;
end if;
end if;
end process;
end Behavioral;
In VHDL, successive assignments to the same signal in a process overrides previous assignments, thus:
if (Lower(0) = '0' and LowerPrevLSB = '1') then
Upper <= Upper + A;
elsif (Lower(0) = '1' and LowerPrevLSB = '0') then
Upper <= Upper + A_2sComp;
end if;
...
Upper <= Product(Product'length - 1 downto MIN(numBits_X, numBits_Y));
The first assignments, in the if block, is completely ignored. If you look at your code, assignments to Product, Upper and Lower are overridden.
I suggest you simulate your design before synthesizing your design with Xilinx. It will be much easier to test and debug. For instance, your counter signal is never reset, and will count up to 2^31-1, then wrap to -2^31. What will happen to your design in those cases? Simulation would point out these error easily, leave synthesis for later!
I'm trying to do a VHDL code with the objective to make a 8 bit LFSR and show all the random states, and after one cycle (when the last state be the same seed value) it stop. But I'm have a problems, keep saying: "loop must terminate within 10,000 iterations". I'm using Quartus II-Altera.
Code:
entity lfsr_8bit is
--generic ( n : integer := 2**8 );
port (
clk : in bit;
rst : in bit;
lfsr : out bit_vector(7 downto 0)
);
end lfsr_8bit;
architecture behaviour of lfsr_8bit is
--signal i : integer := 0;
--signal seed : bit_vector(7 downto 0) := "10000000";
signal rand : bit_vector(7 downto 0);
begin
ciclo : process (clk,rst)
begin
loop
if (rst='0') then
rand <= "10000000";
elsif (clk'event and clk='1') then
rand(0) <= rand(6) xor rand(7);
rand(7 downto 1) <= rand(6 downto 0);
end if;
-- wait until rand = "10000000" for 100 ns;
exit when rand = "10000000";
-- case rand is
-- when "10000000" => EXIT;
-- when others => NULL;
-- end case;
-- i <= i +1;
end loop;
lfsr <= rand(7 downto 0);
end process ciclo;
end behaviour;
Thank you for all help.
Get rid of that loop, that loop does not work the way you think it does! Stop thinking like a software designer and think like a hardware designer. Loops in hardware are used to replicate logic. So that loop of yours is literally trying to generate 10,000 LFSRs!
I don't believe that you need to be using that loop there at all. If you remove it your LFSR should work as intended. You may need to add a control signal to enable/disable the LFSR, but definitely do not use a loop.
Here's some example code demonstrating this. Change the default value of rand to something else or the LFSR will never run! It will immediately set the lfsr_done signal.
ciclo : process (clk,rst)
begin
if (rst='0') then
rand <= "10000000"; -- SET THIS TO SOMETHING DIFFERENT
lfsr_done <= '0';
elsif (clk'event and clk='1') then
if rand = "10000000" then
lfsr_done <= '1';
end if;
if lfsr_done = '0' then
rand(0) <= rand(6) xor rand(7);
rand(7 downto 1) <= rand(6 downto 0);
end if;
end if;
I have a question which is probably in 2 parts:
I am using a (nominally 32 bit) integer variable which I would like to write to an 8 bit UART as 4 bytes (i.e., as binary data)
i.e. variable Count : integer range 0 to 2147483647;
How should I chop the 32 bit integer variable into 4 separate 8 bit std_logic_vectors as expected by my UART code, and how should I pass these to the UART one byte at a time ?
I am aware std_logic_vector(to_unsigned(Count, 32)) will convert the integer variable into a 32 bit std_logic_vector, but then what ? Should I create a 32 bit std_logic_vector, assign the converted Count value to it, then subdivide it using something like the following code ? I realise the following assumes the count variable does not change during the 4 clock cycles, and assumes the UART can accept a new byte every clock cycle, and lacks any means of re-triggering the 4 byte transmit cycle, but am I on the right track here, or is there a better way ?
variable CountOut : std_logic_vector(31 downto 0);
process (clock)
variable Index : integer range 0 to 4 := 0;
begin
if rising_edge(clock) then
CountOut <= std_logic_vector(to_unsigned(Count, 32);
if (Index = 0) then
UartData(7 downto 0) <= CountOut(31 downto 24);
Index := 1;
elsif (Index = 1) then
UartData(7 downto 0) <= CountOut(23 downto 16);
Index := 2;
elsif (Index = 2) then
UartData(7 downto 0) <= CountOut(15 downto 8);
Index := 3;
elsif (Index =31) then
UartData(7 downto 0) <= CountOut(7 downto 0);
Index := 4;
else
Index := Index;
end if;
end if;
end process;
Any comments or recommendations would be appreciated.
Thanks,
MAI-AU.
You seem to be on the right track. I believe there are two basic solutions to this problem:
Register the output value as a 32-bit vector, and use different ranges for each output operation (as you did in your code example)
Register the output value as a 32-bit vector, and shift this value 8 bits at a time after each output operation. This way you can use the same range in all operations. The code below should give you an idea:
process (clock)
variable Index: integer range 0 to 4 := 0;
begin
if rising_edge(clock) then
if (Index = 0) then
CountOut <= std_logic_vector(to_unsigned(Count, 32));
Index := Index + 1;
elsif (Index < 4) then
UartData <= CountOut(31 downto 24);
CountOut <= CountOut sll 8;
Index := Index + 1;
end if;
end if;
end process;
Also, please check your assignments, in your example CountOut is declared as a variable but is assigned to as a signal.
There's nothing wrong with the code you've shown. You can do something to separate the the assignment to UartData using Index to allow a loop.
library ieee;
use ieee.std_logic_1164.all;
entity union is
end entity;
architecture foo of union is
type union32 is array (integer range 1 to 4) of std_logic_vector(7 downto 0);
signal UartData: std_logic_vector(7 downto 0);
begin
TEST:
process
variable quad: union32;
constant fourbytes: std_logic_vector(31 downto 0) := X"deadbeef";
begin
quad := union32'(fourbytes(31 downto 24), fourbytes(23 downto 16),
fourbytes(15 downto 8),fourbytes(7 downto 0));
for i in union32'RANGE loop
wait for 9.6 us;
UartData <= Quad(i);
end loop;
wait for 9.6 us; -- to display the last byte
wait; -- one ping only
end process;
end architecture;
Or use a type conversion function to hide complexity:
library ieee;
use ieee.std_logic_1164.all;
entity union is
type union32 is array (integer range 1 to 4) of std_logic_vector(7 downto 0);
end entity;
architecture fee of union is
signal UartData: std_logic_vector(7 downto 0);
function toquad (inp: std_logic_vector(31 downto 0)) return union32 is
begin
return union32'(inp(31 downto 24), inp(23 downto 16),
inp(15 downto 8), inp( 7 downto 0));
end function;
begin
TEST:
process
variable quad: union32;
constant fourbytes: std_logic_vector(31 downto 0) := X"deadbeef";
begin
quad := toquad (fourbytes);
for i in union32'RANGE loop
wait for 9.6 us;
UartData <= Quad(i);
end loop;
wait for 9.6 us; -- to display the last byte
wait; -- one ping only
end process;
end architecture;
And gives the same answer.