VHDL If problems - if-statement

I am trying to learn VHDL, and it is not going that well..
I wrote this piece of code,
library IEEE;
use IEEE.bit_1164.ALL;
use IEEE.bit_ARITH.ALL;
use IEEE.bit_UNSIGNED.ALL;
entity Switch_led is
port(
Switch_0: in bit;
Switch_1: in bit;
Switch_2: in bit;
Switch_3: in bit;
Switch_4: in bit;
Switch_5: in bit;
Switch_6: in bit;
Switch_7: in bit;
Led_0: out bit;
Led_1: out bit;
Led_2: out bit;
Led_3: out bit;
Led_4: out bit;
Led_5: out bit;
Led_6: out bit;
Led_7: out bit
);
end Switch_led;
architecture Behavioral of Switch_led is
begin
if Switch_0 = '1' then
Led_0 <= 1;
elsif Switch_1 = '1' then
Led_1 <= 1;
elsif Switch_2 = '1' then
Led_2 <= 1;
elsif Switch_3 = '1' then
Led_3 <= 1;
elsif Switch_4 = '1' then
Led_4 <= 1;
elsif Switch_5 = '1' then
Led_5 <= 1;
elsif Switch_6 = '1' then
Led_6 <= 1;
elsif Switch_7 = '1' then
Led_7 <= 1;
end if;
end Behavioral;
For some reason i get errors to my if statements in my architecture. But I aren't able to find what the mistake is. I hope the code makes sense.

The enumeration names for type bit are given in package standard.
type BIT is ('0', '1');
These sort of assignments:
Led_0 <= 1;
Should look like:
Led_0 <= '1';
You'll also note that an if statement is used in a place suitable for a sequential statement, meaning all those should be in a process statement.
SWITCH:
process (Switch_0,Switch_1,Switch_2,Switch_3,Switch_4,Switch_5, Switch_6,Switch_7)
begin
if Switch_0 = '1' then
Led_0 <= '1';
elsif Switch_1 = '1' then
Led_1 <= '1';
elsif Switch_2 = '1' then
Led_2 <= '1';
elsif Switch_3 = '1' then
Led_3 <= '1';
elsif Switch_4 = '1' then
Led_4 <= '1';
elsif Switch_5 = '1' then
Led_5 <= '1';
elsif Switch_6 = '1' then
Led_6 <= '1';
elsif Switch_7 = '1' then
Led_7 <= '1';
end if;
end process;
You could also note that the if elsif will evaluate switches in a particular order and only take effect for the highest priority switch (first in the if then elsif then end if structure).
There aren't any ieee packages with a primary name starting with 'bit':
-- IEEE.bit_1164.ALL;
-- use IEEE.bit_ARITH.ALL;
-- use IEEE.bit_UNSIGNED.ALL;
(And you could have used std_logic).
because the mentioning of switches and LEDs you should be aware that you have only one value assigned to any of the LEDs, they will go on (the leftmost value of BIT) and when turned on, stay on if successfully synthesized and implemented in an FPGA.
Led_0 <= Switch_0; -- as a concurrent signal assignment statement.
One easy way to get rid of this phenomenon would be to not use if statements, where the LED value is related directly to switch value. Should you not want to infer simply wires joining ports you could use an else for each if statement, inside the process.
if Switch_0 = '1' then
Led_0 <= '1';
else
Led_0 <= '0';
end if;
Then there's the concurrent signal assignment statement equivalent of an if statement in a place suitable for a concurrent statement (not inside a process statement):
Led_0 <= '1' when Switch_0 = '1' else '0';
These statements would be independent or concurrent.

Besides David's comprehensive answer, I though I should add that VHDL has a great support for array types, and knowing how to use them is fundamental to writing more compact code.
A one-dimensional array of bits is called a bit_vector. Because you can assign to all the values in a bit_vector at once, your code could be made much more simple:
entity switches_to_leds is
port (
switches: in bit_vector(7 downto 0);
leds: out bit_vector(7 downto 0)
);
end;
architecture behavior of switches_to_leds is
begin
leds <= switches;
end;
Also take a look at the types std_logic and std_logic_vector, which are the industry standard for interfacing between digital circuits.

Related

VHDL - "Input is never used warning"

I've written a program in VHDL (for Xilinx Spartan-6) that increments a counter whilst a button is pressed and resets it to zero when another button is pressed.
However, my process throws the error WARNING:Xst:647 - Input is never used. This port will be preserved and left unconnected... for the reset variables - despite the fact that it is used both in the sensitivity of the process and as a condition (just as much as button, yet that doesn't get flagged!).
binary_proc : process(CLK_1Hz, button, reset) --include all inputs on sensitivity list
begin
if rising_edge(CLK_1Hz) and button = '1' then
binary <= binary + 1;
else if reset = '1' then
binary <= (others => '0');
end if;
end if;
end process;
More curiously though, I can fix this by simply using two if statements rather than just an if-else if statement, as shown below;
binary_proc : process(CLK_1Hz, button, reset) --include all inputs on sensitivity list
begin
if rising_edge(CLK_1Hz) and button = '1' then
binary <= binary + 1;
end if;
if reset = '1' then
binary <= (others => '0');
end if;
end process;
My question is: why is the reset variable optimized out of the circuit when an if-else statement is used but not when two if statements are used? What causes this and how can this sort of thing be avoided it?
Thanks very much!
NB: Full code of the program is below in case it helps!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity button_press is
port(
CLK_200MHz : in std_logic;
button : in std_logic;
reset : in std_logic;
LED : out std_logic_vector(3 downto 0) --array of LED's
);
end button_press;
architecture Behavioral of button_press is
signal CLK_1Hz : std_logic; --input clock (think 200 MHz)
signal counter : std_logic_vector(26 downto 0); --counter to turn 200 MHz clock to 1 Hz
signal binary : std_logic_vector(3 downto 0); --binary vector thats mapped to LED's
begin
-----Create 1 Hz clock signal from 200 MHz system clock-------
prescaler : process(CLK_200MHz)
begin
if rising_edge(CLK_200MHz) then
if (counter < 2500000) then --possibly change to number in binary
counter <= counter + 1;
else
CLK_1Hz <= not CLK_1Hz; --toggle 1 Hz clock
counter <= (others => '0'); --reset counter to 0
end if;
end if;
end process;
------ Increment binary number when on rising clock edge when button pressed -------
binary_proc : process(CLK_1Hz, button, reset) --include all inputs on sensitivity list
begin
if rising_edge(CLK_1Hz) and button = '1' then
binary <= binary + 1;
end if;
if reset = '1' then
binary <= (others => '0');
end if;
end process;
LED <= binary; --map binary number to LED's
end Behavioral;
The problem is, that reset is conditional to not (rising_edge(CLK_1Hz) and button = '1'), and the Xilinx XST tool can't figure out how to map this to FPGA hardware.
VHDL is a Hardware Description Language (HDL part of VHDL), so don't think of it like writing another program (e.g. as in C or Python), but think of it as describing a circuit.
Converting VHDL code to hardware is a complicated task, and Xilinx expects the designer to use some patterns, as described in the "XST Hardware Description Language
(HDL) Coding Techniques" of the Xilinx XST User Guide. The first code part does not follow any of these patterns, and XST fails to convert this to hardware, thus the warning.
As per that coding style, the way to write it would be:
process(CLK_1Hz, reset) is -- Don't include button, since sync. signal
begin
if reset = '1' then
binary <= (others => '0');
elsif rising_edge(CLK_1Hz) then
if button = '1' then
binary <= binary + 1;
end if;
end if;
end process;
Btw. consider not making an extra clock as CLK_1Hz, but make an increment enable signal instead, since every clock requires special handling and resources.

How can i generate a pulse train to give output in common way?

I am working on generating a 40 bit length pulse train. I also must be able to adjust the frequency. I tried to make a new low frequency clock and i make a new counter which counts on it's rising edges and give an high output and terminating after 40 bit. It's not working. I tried some other methods. They are not, too.
For example;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity con40 is port(clk:in std_ulogic; q:out std_ulogic);
end entity con40;
architecture Behaviour of con40 is
constant s:std_ulogic_vector:="11111111111111111111111111111111";
signal i:unsigned(4 downto 0):="00000";
signal en:std_logic:='1';
signal reset:std_logic:='0';
begin
q<=s(to_integer(i));
process(reset,clk) is begin
if reset='1' then
i<=(others=>'0');
elsif rising_edge(clk) then
if en='1' then
i<=i+1;
end if;
end if;
end process;
end architecture Behaviour;
There is 32-bit length in this code but i wanna make 40 bit but whatever, this is not working too. I think methods for such a pulse train must be common and they are being used widely. But hey! unluckily i can find nothing useful.
I took the liberty of moving en and reset to port signals, also changed your constant to a recognizable 40 bit value, and specified the range to make it a locally static constant.
The issue with your counter is that it isn't big enough to address 40 bits. You have i specified as a 5 bit value while 40 bits requires a 6 bit counter.
I also added a second architecture here with i as an integer type signal. With i as either an unsigned value or an integer type you likely need to roll over the i counter at 39 ("100111") when the first position is 0 ("000000").
library ieee;
use ieee.std_logic_1164.all;
entity con40 is
port(
reset: in std_ulogic;
clk: in std_ulogic;
en: in std_ulogic;
q: out std_ulogic
);
end entity con40;
architecture foo of con40 is
constant s: std_ulogic_vector (0 to 39) := x"feedfacedb";
signal i: natural range 0 to 39;
begin
q <= s(i);
process (reset, clk)
begin
if reset = '1' then
i <= 0;
elsif rising_edge(clk) and en = '1' then
if i = 39 then
i <= 0;
else
i <= i + 1;
end if;
end if;
end process;
end architecture;
library ieee;
use ieee.numeric_std.all;
architecture behave of con40 is
constant s: std_ulogic_vector (0 to 39) := x"feedfacedb";
signal i: unsigned (5 downto 0);
begin
q <= s(to_integer(i));
process (reset, clk)
begin
if reset = '1' then
i <= "000000";
elsif rising_edge(clk) and en = '1' then
if i = "100111" then
i <= "000000";
else
i <= i + 1;
end if;
end if;
end process;
end architecture;
I also did a quick and dirty test bench:
library ieee;
use ieee.std_logic_1164.all;
entity tb_con40 is
end entity;
architecture foo of tb_con40 is
signal clk: std_ulogic := '0';
signal reset: std_ulogic := '1';
signal en: std_ulogic := '0';
signal q: std_ulogic;
begin
DUT:
entity work.con40
port map (
reset => reset,
clk => clk,
en => en,
q => q
);
CLOCK:
process
begin
for i in 0 to 46 loop
wait for 20 ns;
clk <= not clk;
wait for 20 ns;
clk <= not clk;
end loop;
wait;
end process;
STIMULUS1:
reset <= '0' after 40 ns;
STIMULUS2:
en <= '1' after 60 ns;
end architecture;
Which can demonstrate the correct output:
addendum in response to comment question
The pattern X"FEEDFACEDB" is 40 bits long and was substituted for the 32 all '1's value for constant s to demonstrate that you are actually addressing individual elements of the s array value.
To stop the pulse train fro recurring:
For architecture foo (using an integer type for i):
elsif rising_edge(clk) and en = '1' then
-- if i = 39 then
-- i <= 0;
-- else
if i /= 39 then -- added
i <= i + 1;
end if;
This stops the counter from operating when it reaches 39.
For architecture behave (using an unsigned type for i):
elsif rising_edge(clk) and en = '1' then
-- if i = "100111" then
-- i <= "000000";
-- else
if i /= "100111" then -- added
i <= i + 1;
end if;
end if;
Both architectures behave identically stopping the i counter at 39 ("100111").
The counter can be shown to have stopped by simulating:
Without adding an additional control input the only way to get the pulse stream to occur a second time would be by invoking reseet.
The following code could be a simple implementation to generate pulse trains. This module requires a start impulse (StartSequence) and acknowledges the generated sequence with 'SequenceCompleted'.
Instead of an state machine I use a basic RS flip flop with set = StartSequence and rst = SequenceCompleted_i. I also broke up the process into two processes:
state control - this can be extended to a full FSM if needed
used for counter(s)
Initially, the module emits PULSE_TRAIN(0) by default and also after each sequence generation. So if you want to emit 40 ones otherwise zero set PULSE_TRAIN := (0 => '0', 1 to 40 => '1')
This module is variable in the bit count of PULSE_TRAIN, so I needed to include a function called log2ceil, which calculates the 2s logarithm aka needed bits from PULSE_TRAIN's length attribute.
So in case of 'length = 41 bits Counter_us has a range of (5 downto 0).
entity PulseTrain is
generic (
PULSE_TRAIN : STD_LOGIC_VECTOR
);
port (
Clock : in STD_LOGIC;
StartSequence : in STD_LOGIC;
SequenceCompleted : out STD_LOGIC;
Output : out STD_LOGIC
);
end entity;
architecture rtl of PulseTrain is
function log2ceil(arg : POSITIVE) return NATURAL is
variable tmp : POSITIVE := 1;
variable log : NATURAL := 0;
begin
if arg = 1 then return 0; end if;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
signal State : STD_LOGIC := '0';
signal Counter_us : UNSIGNED(log2ceil(PULSE_TRAIN'length) - 1 downto 0) := (others => '0');
signal SequenceCompleted_i : STD_LOGIC;
begin
process(Clock) is
begin
if rising_edge(Clock) then
if (StartSequence = '1') then
State <= '1';
elsif (SequenceCompleted_i = '1') then
State <= '0';
end if;
end if;
end process;
SequenceCompleted_i <= '1' when (Counter_us = (PULSE_TRAIN'length - 1)) else '0';
SequenceCompleted <= SequenceCompleted_i;
process(Clock)
begin
if rising_edge(Clock) then
if (State = '0') then
Counter_us <= (others => '0');
else
Counter_us <= Counter_us + 1;
end if;
end if;
end process;
Output <= PULSE_TRAIN(to_integer(Counter_us));
end;
As what #fru1tbat mentioned, it's not really clear what is "not working" and what you really intend to do. If you would really just want to generate a pulse train, one would think you want to generate a series of alternating '1' and '0', not all '1's like in the code you posted.
Also, the i counter just counts up, and can only be reset to '0' by use of the reset signal, which is fine as long as you intended it that way.
If you'd like to generate a train of '1's and '0's, you'd need something like this (not tested, but should be along these lines):
architecture behaviour of con40 is
constant trainLength:positive:=80;
signal i:unsigned(6 downto 0):=(others=>'0');
...
begin
process(reset,clk) is begin
if reset then
i<=(others=>'0');
q<='0';
elsif rising_edge(clk) then
q<='0'; -- default assignment.
-- Defaults to '0' when if-statement fails.
if i<trainLength then
i<=i+1;
q<=not q;
end if;
end if;
end process;
end architecture behaviour;
This gives you a single-shot pulse train, means there is no way to repeat generation of the pulse train unless you assert the reset signal again. This is fine if it's what you want, otherwise, you'll need more signals to cater for cases where you'd like to re-generate the pulse train without resetting.
Here, I'm assuming you'd like 40 HIGH pulses, which essentially makes the train length 80 clock cycles, not 40. Also, I'm assuming you want a 50% duty cycle, i.e. the HIGH and LOW times are equal. Depending on your requirements, you may need a pulse width that is longer or shorter.
With these assumptions in mind, you'd need at least a 7-bit counter to count 80 clocks. You may think of other better ways to do this as well, but this just comes off the top of my head, and is probably a good place to start.
If your tool doesn't yet support VHDL-2008's enhanced port modes (e.g. ability to read from out-mode ports), then you could declare q as having a buffer mode instead of out. If your tool doesn't support buffer port modes, then you can declare an internal signal and use it for your logic. E.g.:
signal i_q: std_ulogic;
...
i_q<=not i_q; -- use internal signal for logic instead.
q<=i_q; -- drive output from internal signal.
To adjust the frequency, simply supply a higher or lower frequency into your clk input. This can be generated from another PLL, or a frequency divider, or any other oscillating circuitry you have available. Just supply its output into your clk.
Hope this helps.

VHDL - PhysDesignRules:367

I am getting a warning when i try synthesize,implement, and generate program file from my VHDL Code.
When i try to synthesize i get this error
WARNING:Xst:647 - Input <BTN_3> 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.
When i Implement it i get this
WARNING:PhysDesignRules:367 - The signal <BTN_3_IBUF> is incomplete. The signal
does not drive any load pins in the design.
WARNING:Par:288 - The signal BTN_3_IBUF has no load.
PAR will not attempt to route this signal.
WARNING:Par:283 - There are 1 loadless signals in this design.
This design will cause Bitgen to issue DRC warnings.
and when i generate program file i get this error
WARNING:PhysDesignRules:367 - The signal <BTN_3_IBUF> is incomplete.
The signal does not drive any load pins in the design.
What could cause this error..
The code can be found here [http://pastebin.com/eK05tyEb][1]
[1]: http://pastebin.com/eK05tyEb - link to the code
User constrain file /.Ucf
NET "Switch_0" LOC = "G18";
NET "Switch_1" LOC = "H18";
NET "Switch_2" LOC = "K18";
NET "Switch_3" LOC = "K17";
NET "Switch_4" LOC = "L14";
NET "Switch_5" LOC = "L13";
NET "Switch_6" LOC = "N17";
NET "Switch_7" LOC = "R17";
NET "LED_0" LOC = "J14";
NET "LED_1" LOC = "J15";
NET "LED_2" LOC = "K15";
NET "LED_3" LOC = "K14";
NET "LED_4" LOC = "E17";
NET "LED_5" LOC = "P15";
NET "LED_6" LOC = "F4";
NET "LED_7" LOC = "R4";
NET "BTN_3" LOC = "H13";
Your code as you have posted may not tell the entire story. Normally there is an interface (user constraints, thanks Bob) file that defines pin edge inputs and outputs to a port of a circuit internal to the FPGA you define. I am not seeing that.
Secondly, I also see in your code that you have 2 differing circuits driving each one of your output LEDs.
You have an if statement that checks for BTN_3 being 1, which will drive ALL of the LEDs to 0, then a set of If statements checking the input state of each "Switch_X" which individually drives a 0 or one to each LED. This is actually illegal. You can only have one circuit driving any output port.
What you should do is write this circuit as follows:
architecture Behavioral of Switch_led is
begin
Process(Switch_0, Switch_1, Switch_2, Switch_3, Switch_4, Switch_5, Switch_6 , Switch_7, BTN_3)
begin
if BTN_3 = '1' then
Led_0 <= '0';
Led_1 <= '0';
Led_2 <= '0';
Led_3 <= '0';
Led_4 <= '0';
Led_5 <= '0';
Led_6 <= '0';
Led_7 <= '0';
else
if Switch_0 = '1' then
Led_0 <= '1';
else
Led_0 <= '0';
end if;
if Switch_1 = '1' then
Led_1 <= '1';
else
Led_1 <= '0';
end if;
if Switch_2 = '1' then
Led_2 <= '1';
else
Led_2 <= '0';
end if;
if Switch_3 = '1' then
Led_3 <= '1';
else
Led_3 <= '0';
end if;
if Switch_4 = '1' then
Led_4 <= '1';
else
Led_4 <= '0';
end if;
if Switch_4 = '1' then
Led_4 <= '1';
else
Led_4 <= '0';
end if;
if Switch_5 = '1' then
Led_5 <= '1';
else
Led_5 <= '0';
end if;
if Switch_6 = '1' then
Led_6 <= '1';
else
Led_6 <= '0';
end if;
if Switch_7 = '1' then
Led_7 <= '1';
else
Led_7 <= '0';
end if;
end if;
end process;
end Behavioral;
What I have essentially done is to bring all of your individual Switch_X checking into the else clause of the btn_3 check. This forces what I was stating before, that only one logic circuit will drive any LED at any point in time.

Changing IF statements, saving some code

Hello friends and pro programmers, im new to this world of VHDL and i have this question.
i want to make this:
if counter >= 0 and counter <=95 then
aux_Hs <= '0';
else
aux_Hx <= '1';
end if;
in something like this:
aux_Hs <= (counter >= 0 and counter <=95);
this error shows up:
Line 73. Type of aux_Hs is incompatible with type of and.
aux_Hs is a signal STD_Logic.
is there some way to save the IF statements? a pseudo " ? : " instruction?.
Thank you in advance :)
As concurrent code, without VHDL-2008:
aux_Hs <= '1' when (counter >= 0 and counter <=95) else '0' ;
With VHDL-2008:
aux_Hs <= counter ?>= 0 and counter ?<=95 ;
If you need to do this inside a process, you can save a line of code like this:
aux_Hs <= '0';
if not (counter >= 0 and counter <=95) then
aux_Hx <= '1';
end if;
Or you can use VHDL-2008 (look for the switches on your compiler and log a bug if VHDL2008 is not supported!) which allows conditional assigment inside processes:
aux_Hs <= '0' when (counter >= 0 and counter <=95) else '1' ;

Concurrent If Statements in VHDL

I am writing code for comparing a signal to a number of signals at the same time.
Here is the example:
process (CLK, reset)
if reset = '0' then
data <= (others => '0');
elsif rising_edge (CLK) then
if A = B then
data <= data OR "0001";
else data <= data AND "1110";
end if;
if A = C then
data <= data OR "0010";
else data <= data AND "1101";
end if;
if A = D then
data <= data OR "0100";
else data <= data AND "1011";
end if;
if A = E then
data <= data OR "1000";
else data <= data AND "0111";
end if;
end if;
end process;
I just want to comparing the A to B, C, D and E signals and then turn the associated bits in data on and off. The code I wrote above is not working since the synthesis tool will optimize the B, C and D if statements and only leaving the E if statement. I have also thought about using case - when statement but it doesn't have a mechanism to turn off the associated single bit off. When others can only turn all 4 bits off. What is the effective way to do this? Thanks!
BTW, are all these 4 if statements run at the same time? Or they are run at different cycles? I guess they would run one by one, otherwise it would cause fan-in.
You are trying to write C in a language where you don't have to!
In C you can't access a single bit, only bytes and larger units so C programmers have to resort to AND/OR i.e. &,| to set or clear bits.
In VHDL you can address individual bits of a word, and write
if A = B then
data(0) <= '1';
else
data(0) <= '0';
end if;
Much simpler. And yes they all run at the same time, every clock cycle.
I would prefer to declare data as an array of booleans,
signal data : array(3 downto 0) of boolean;
Then I could write
process (CLK, reset)
begin
if reset = '0' then
data <= (others => false);
elsif rising_edge (CLK) then
data <= (A = E) & (A = D) & (A = C) & (A = B);
end if;
end process;
If I had to use a std_logic_vector for data, the convenience of this form is (almost) tempting enough to make me overload the "=" operator for A's type with one returning std_logic.
Then, for the price of writing a tiny function, I could keep this code.
EDIT:
To address the reason the original approach doesn't work, it is necessary to understand the semantics of signal assignment, as explained for example here.
So the first assignment to Data (for A=B) is stored up to happen after the process suspends. Then the second assignment replaces it BEFORE IT HAPPENED so the first such assignment never takes place.
What you need for the original approach to work, is a variable because variable assignments happen immediately.
process (CLK, reset)
variable data_int : whatever; -- same type as data
begin
if reset = '0' then
data <= (others => '0');
elsif rising_edge (CLK) then
data_int := data;
if A = B then
data_int := data_int OR "0001";
else data_int := data_int AND "1110";
end if;
...
if A = E then
data_int := data_int OR "1000";
else data_int := data_int AND "0111";
end if;
data <= data_int;
end if;
end process;
Now the single assignment to data will contain all the separate modifications. However it might synthesise to something much larger than the optimal solutions.