I am new to VHDL and working with case statements, I have something like the following:
process(state)
begin
case state is
when stop =>
a <= input;
b <= output;
when move =>
a <= input_1;
b <= output_1;
end case;
end process;
where a,b,input, output,input_1 and output 1 are signals.
My issue is that I want to have a nested case in only one of the options:
for example:
process(state)
begin
case state is
when stop =>
a <= input;
b <= output;
when move =>
a <= if c='0' then input_1 else input_2;
b <= if c='0' then output_1 else output_2;
end case;
end process;
My question is can i do something like above where not all case options are nested but only some of them are or is there any other way in such situation , i tried using when else but got an error, saying that such syntax is not supported.
Any help is appreciated
I'm not quite sure what you're asking here:
can i do something like above where not all case options are nested but only some of them are or is there any other way in such situation
but is this what you are trying to do? (Note that I've added c to the sensitivity list):
process(state,c)
begin
case state is
when stop =>
a <= input;
b <= output;
when move =>
case c is
when '0' =>
a <= input_1;
b <= output_1;
when '1' =>
a <= input_2;
b <= output_2;
when others => null;
end case;
end process;
Your question is fraught with perils. Assigning an output to an internal signal can require an output port mode of inout or buffer or VHDL 2008 support which isn't universal for synthesis. Generally mode buffer isn't supported either.
To get to the heart of your question sequential signal assignments supporting when else are supported in VHDL 2008 but not generally in synthesis.
A case statement choice contains sequential statements.
You can use an if statement instead:
library ieee;
use ieee.std_logic_1164.all;
entity foo is
port (
signal input: in std_logic;
signal output: inout std_logic;
signal input_1: in std_logic;
signal input_2: in std_logic;
signal output_1: inout std_logic;
signal output_2: inout std_logic
);
end entity;
architecture fum of foo is
signal a, b: std_logic;
signal c: std_logic;
type some_state is (stop, move);
signal state: some_state;
begin
UNLABELED:
process(state)
begin
case state is
when stop =>
a <= input;
b <= output;
when move =>
if c = '0' then
a <= input_1;
b <= output_1;
else
a <= input_2;
b <= output_2;
end if;
end case;
end process;
end architecture;
Notice your two evaluations of c have been collapsed into one.
Besides the conditional signal assignment states that are supported as sequential statements in VHDL 2008, there's also selected signal assignment statements (likewise generally not supported by synthesis as sequential statements).
VHDL before 2008 does not have a ternary operator (C-like ? :) for sequential
statements, so you can't write if c='0' then input_1 else input_2, but in
VHDL-2008 you can write input_1 when c='0' else input_2.
However, the compact coding style can be achieved by making a small function:
function ternary(cond : boolean; res_true, res_false : std_logic) return std_logic is
begin
if cond then
return res_true;
else
return res_false;
end if;
end function;
Whereby the move part of the code can be written like:
when move =>
a <= ternary(c='0', input_1, input_2);
b <= ternary(c='0', output_1, output_2);
You can also make a nested case like:
when move =>
case c is
when '0' =>
a <= input_1;
b <= output_1;
when others =>
a <= input_2;
b <= output_2;
end case;
Or do it with if then else as David showed.
Related
I have a simple VHDL code which has two process. The second process updates the output port m_LED based on the state CF value. In simulation I see the behavior as expected. But when I program the FPGA I noticed that, the output port m_LED is producing some random values which is not even assigned in the code. I am totally clueless from where these values are coming. Any hint will be much appreciated!
entity monitor is
Port (
io_LED: in std_logic_vector(3 downto 0);
m_LED: out std_logic_vector(3 downto 0)
);
end monitor;
architecture Behavioral of monitor is
type state_type is (s0, s1, s2,s3);
signal state: state_type :=s0;
signal nrst:std_logic:='1';
begin
Process (io_LED)
begin
if (nrst= '0') then
state<= s0;
else
case state is
when s1 =>
if (io_LED = "0000") then
state <= s2;
end if;
when others => state <= s0;
end case;
end if;
end Process;
Process(io_LED)
begin
m_LED<="0000";
case state is
when s0 =>
m_LED<="0000";
when s1 =>
m_LED<="0001";
when others => m_LED<="0000";
end case;
end Process;
end Behavioral;
I believe that what you are doing is a very long combinational path for a state machine. State machines are better implemented using a register to actually keep the state.
The downside is that you will need to provide a clock for the state register to sample the input and launch the output.
Changes:
CF is made as a register CF_r, to hold the state.\
First process is a sequential process, with the CF_r register holding the code { i, t, f,e } as defined by the input.
CF is the only element in the second process sensitivity list as it is a combinational output based only on the state.
-- Synchronous reset
entity monitor is
Port (
io_LED: in std_logic_vector(3 downto 0);
monit_LED: out std_logic_vector(3 downto 0)
);
end monitor;
architecture Behavioral of monitor is
type Code is (i, t, f,e);
signal CF_r: Code:=i;
signal nrst:std_logic:='1';
begin
-- Synchronous reset
Process (clk)
begin
if rising_edge(clk) then
if (nrst= '0') then --should be adapted to postive logic
CF_r <= t; --reset
else
case CF_r is
when i =>
if (io_LED = "0000") then
CF_r <= t;
end if;
when t =>
if (io_LED = "0001") then
CF_r <= f;
else
CF_r <=e;
end if;
when f =>
if (io_LED = "0010") then
CF_r <= t;
else
CF_r <=e;
end if;
when others => CF_r <= i;
end case;
end if;
end if;
end Process;
-- The output depends only on the state
Process(CF_r)
begin
case CF_r is
when i =>
monit_LED<="0000";
when t =>
monit_LED<="0001";
when f =>
monit_LED<="0010";
when e =>
monit_LED<="1111";
when others => monit_LED<="0000";
end case;
end Process;
end Behavioral;
I need to share a value (a real) between two process, but when I try to run my code, quartus gives me an error.
library IEEE;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
use IEEE.MATH_REAL.ALL;
entity de0nano is
port (
CLOCK_50 : in std_logic;
KEY : in std_logic_vector(1 downto 0);
SW : in std_logic_vector(3 downto 0);
LED : out std_logic_vector(7 downto 0);
GPIO : inout std_logic_vector(35 downto 0)
);
end de0nano;
architecture struct of de0nano is
--declarations
signal PN : real :=0.0 ;
signal PR : real :=0.0 ;
signal RC : integer :=1;
signal NC : integer :=1;
signal BET : integer :=1;
begin
count : process (CLOCK_50, GPIO)
begin
--A <= KEY(0);
GPIO(24) <= '1';
--functional coding
LED <= "00011000";
if (pn > pr) then
GPIO(26) <= '1';
LED <= "00000001";
else
GPIO(26) <= '0';
end if;
if (pn = pr) then
GPIO(26) <= '1';
LED <= "00000010";
else
GPIO(26) <= '0';
end if;
if (pn < pr) then
GPIO(26) <= '1';
LED <= "00000011";
else
GPIO(26) <= '0';
end if;
end process;
probabilityController : process (CLOCK_50, KEY)
begin
--stato iniziale
if((RC + NC + BET)=1) then
pr <= 0.5;
pn <= 0.5;
end if;
--sequenza rossi consecutivi
if(RC>0) then
pr <= (5)**RC;
pn <= 1- (5)**RC;
end if;
--sequenza neri consecutivi
if(NC>0) then
pr <= (5)**NC;
pn <= 1- (5)**NC;
end if;
end process;
betController : process (CLOCK_50)
begin
end process;
colorController : process (CLOCK_50, KEY)
begin
if(KEY(0)='1') then
NC<=0;
RC <= RC+1;
end if;
if(KEY(1)='1') then
RC<=0;
NC <= NC+1;
end if;
end process;
end str
How can I operate in the same signal/variable from two different processes?
VHDL is a hardware description language. A VHDL description can be simulated (executed a bit like you do with most programming languages) or synthesized (transformed in a network of interconnected simple hardware elements). Some tools are pure simulators (Mentor Graphics Modelsim, Cadence ncsim...), others are pure synthesizers (Mentor Graphics Precision RTL, Cadence RTL compiler...) and others can do both. Quartus pertains to the last category. So, the first thing to do is to decide whether you want to simulate, synthesize or both.
In case you want to simulate you must fix three errors:
the position of your signal declaration,
the way you assign it (:=) which is the variable assignment operator, not the signal assignment (<=)
and the fact that you drive it from two processes while it is of an unresolved type (real). See this other answer for resolved / unresolved VHDL types.
Your code could then look like this (but as I do not know what you are trying to do, it is probably not what you want):
architecture V1 of AOI is
Signal foobar : real := 0.0;
begin
OneTwo : process (clk)
Begin
Foobar <= foobar + 2.0;
End process;
end V1;
If you want to synthesize you will have to fix a few more problems:
You are using the real type which is the floating point VHDL type. This is not synthesizable by the synthesizers I know. Indeed, what would you expect the synthesizer to do? Instantiate a complete floating point unit? What brand? So, you will have to replace real by some other type (integers, bit vectors...).
You are assigning your signal on both edges of what I believe is your clock (clk). This is probably not what you want.
You are initializing the signal at declaration time. This is usually not synthesizable by the synthesizers I know. In fact this initialization time has a clear meaning for simulation: it is the beginning of the simulation. But what about hardware? What is the beginning of a piece of hardware? Manufacturing? Power up? So, if you want the signal to be initialized at some point you will have to add a hardware reset, driven by a reset input.
All in all you could have something like:
architecture V1 of AOI is
Signal foobar : natural range 0 to 255;
begin
OneTwo : process (clk)
Begin
if rising_edge(clk) then
if reset = '1' then
foobar <= 0;
else
foobar <= foobar + 2;
end if;
end if;
End process;
end V1;
Notes:
VHDL is case insensitive but you should try to be consistent, it will help you.
You should probably take a VHDL course or read a VHDL primer before trying to use the language. It is radically different from the programming languages you already know. Hardware and software are pretty different worlds, even if they are strongly connected at the end.
I am trying to compare two values in a clk cycle
eg:
if(riding_edge(clk)) then
if (some signal = other) then
other<=other+1;
else other<=other;
if(other=3)then
flag=1;
end if;
end if;
The code compiles and runs fine but when I am seeing the simulation window, the flag gets set no matter what is the value of other. Am I doing something wrong or the value of other is fluctuating.
The above is a pseudo code and everything is correct syntactically.
Please Help
Thanks in advance
Without a minimal working example, I could only guess that you're inferring a latch by not specifying what happens to flag when other is not 3. To prevent this, you would specify all cases of any decision tree.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY example IS
PORT (some_signal : IN STD_LOGIC;
other : IN STD_LOGIC;
clk : IN STD_LOGIC;
flag : OUT STD_LOGIC;
);
END example;
ARCHITECTURE minimal OF example IS
BEGIN
minexample:PROCESS(clk)
BEGIN
IF (clk'EVENT and clk='1') THEN
IF some_signal = other THEN
other <= other + '1';
ELSE other <= other;
END IF;
IF(other = '1') THEN
flag <= '1';
ELSE flag <= '0'; -- always specify all cases
END IF;
END IF;
END PROCESS minexample;
END minimal;
I use the code of N8TRO and add an reset to set the signal to zero at the startup and change the signal other to integer (because you like to check on the value 3) and check on rising_edge (should be the better way).
Now the signal flag should raise to high after 4 clocks after the Reset is set to low. Is this the behavior you expect?
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY example IS
PORT (some_signal : IN STD_LOGIC;
other : IN integer range 0 to 3; --this should be an integer 2 bit widht
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
flag : OUT STD_LOGIC;
);
END example;
ARCHITECTURE minimal OF example IS
BEGIN
minexample:PROCESS(clk,reset)
BEGIN
IF (reset = '1') then --i think a reset is a good idea
flag <= '0';
other <= 0;
ELSIF (rising_edge(clk)) THEN
IF some_signal = other THEN
other <= other + 1;
ELSE
other <= other;
END IF;
IF(other = 3) THEN --other is now an integer, so you can check on 3
flag <= '1';
ELSE
flag <= '0'; -- always specify all cases
END IF;
END IF;
END PROCESS minexample;
END minimal;
I want to compare two binary logic vectors A, and B. However my code won't compile and I am not sure why I am not allowed to use comparison statements here. can anyone help me? My problem is that I am new to VHDL and I need some tips
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--entity declaration of IC74x85 with port definitions
entity IC74x85 is
port( A : in std_logic_vector(3 downto 0); --input A is a 4 bit binary number
B : in std_logic_vector(3 downto 0); --input B is a 4 bit binary number
ALTBOUT : out std_logic; -- A < B
AEQBOUT : out std_logic; -- A = B
AGTBOUT : out std_logic -- A > B
);
end IC74x85;
--architecture of entity
architecture IC74x85_arch of IC74x85 is
begin
process(A,B)
begin
case A is
when (A < B) => ALTBOUT <= '1';
when (A > B) => AGTBOUT <= '1';
when (A = B) => AEQBOUT <= '1';
when others => ALTBOUT, AGTBOUT, AEQBOUT <= '0';
end case;
end process;
end IC74x85_arch;
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(21): Type error resolving infix expression "<" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(21): Choice in CASE statement alternative must be locally static.
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(22): Type error resolving infix expression ">" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(22): Choice in CASE statement alternative must be locally static.
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(23): Type error resolving infix expression "=" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(23): Choice in CASE statement alternative must be locally static.
** Error: C:/Users/Steve/Desktop/Ass1/case signal assignment.vhd(24): near ",": expecting <= or :=
What you are trying to do cannot be accomplished with a case statement, but you can simply write it as an if-then-else. Also, you can't use comparison operations like < and > on std_logic_vectors -- this is something that takes numeric interpretation, so you need to use the signed or unsigned types depending on what kind of numbers you have:
First, include ieee.numeric_std.all:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
Then cast the data types correctly for your comparisons:
process(A,B)
begin
if signed(A) < signed(B) then ALTBOUT <= '1';
elsif signed(A) > signed(B) then AGTBOUT <= '1';
else signed(A) = signed(B) then AEQBOUT <= '1';
else ALTBOUT <=0; AGTBOUT <=0; AEQBOUT <= '0';
end if;
end process;
You can't use a case statement to do this. Your error messages say why:
Type error resolving infix expression "<" as type ieee.std_logic_1164.STD_LOGIC_VECTOR.
You are asking the compiler to choose a case based on the value of A. The code you have written is asking the compiler to compare A (an slv) with A<B which is a boolean. Clearly, that won't ever work.
As answered before, this is a job for the if-elsif-else statements and the signed data type.
However, if for some reason you really wanted to this with a case statement -- as in: "Hey, Joe I'll give you a big bag of money if your can write this in VHDL using a case statement and no if-elsif-else statements." It can be done. Joe Engineer would concatenate the A and B together (it is assumed A and B are 4-bits wide) into an 8-bit std_logic_vector, called C. Then Joe would write a case with C and have 256 when statements -- each when would set ALTBOUT, AGTBOUT, and AEQBOUT to the correct value for each 8-bit pattern.
Of course, this is a silly way to do this (unless someone is going to give you a big bag of money :-) !
BTW: What wjl gave:
process(A,B)
begin
if signed(A) < signed(B) then ALTBOUT <= '1';
elsif signed(A) > signed(B) then AGTBOUT <= '1';
elsif signed(A) = signed(B) then AEQBOUT <= '1';
else ALTBOUT <=0; AGTBOUT <=0; AEQBOUT <= '0';
end if;
end process;
(Sorry, I cannot leave comments to answers, yet, or I would comment on mjl's answer) can be improved (beyond the inferred latch issue): There is no reason to test for A==B. If NOT (A<B) and NOT (A>B) then A must equal B.
process(A,B)
begin
ALTBOUT <=0; AGTBOUT <=0; AEQBOUT <= '0';
if signed(A) < signed(B) then ALTBOUT <= '1';
elsif signed(A) > signed(B) then AGTBOUT <= '1';
else AEQBOUT <= '1';
end if;
end process;
I have stuck on this problem since last week and tried to receive a correct answer from different ways but unfortunately since now it has not worked.
I hae a state machine that receives three patterns and make a matrix for each one of them and then sum all of them together and sends it to output. But the state machine sends the matrix of first pattern to output.
I think the problem is that adder should work with the clock (state one) and state machine goes to the next state with event edge of each clock, therefore it can't synchronize with the adder. But i don't know how i can fix this problem. I would appriciate any help kindly.
P.S The package must be included in the code.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 14:11:16 0NUMBITS-1/11/2012
-- Design Name:
-- Module Name: state_machine - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use work.my_data_types.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity state_machine2 is
port(
pattern : in std_logic_vector(0 to NUMBITS-1); --The incorrect pattern
clk : in std_logic;
result : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1)
);
end state_machine2;
architecture Behavioral of state_machine2 is
type state is (zero , one, two);
signal pr_state, nx_state : state ;
signal s_out_matrix : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1):= (others => (others => (others => '0')));
signal q : integer;
begin
process(clk)
begin
if(clk'event and clk = '1')then
pr_state <= nx_state;
end if;
end process;
process(pattern, pr_state)
variable cnt: integer := -1;
begin
case pr_state is
when zero =>
q <= 0; -- state number
if(cnt < NUM_TRAIN_PATTERN)then
cnt := cnt + 1;
nx_state <= one;
else
nx_state <= two;
end if;
when one =>
q <= 1;
For i in 0 to NUMBITS-1 loop --The multiplication in the pattern
For j in 0 to NUMBITS-1 loop
if(i = j) then
s_out_matrix(i,j) <= (others => '0');
elsif(pattern(i) = pattern(j)) then
s_out_matrix(i,j) <= (0 => '1', others => '0');
else
s_out_matrix(i,j) <= (others => '1');
end if;
end loop;
end loop;
if(clk'event and clk = '1')then -- Sum of the matrixes
For i in 0 to NUMBITS-1 loop
For j in 0 to NUMBITS-1 loop
s_flipflop_adder(i,j) <= s_flipflop_adder(i,j) + s_out_matrix(i,j);
end loop;
end loop;
end if;
nx_state <= zero;
when two =>
q <= 2;
result <= s_flipflop_adder;
end case;
test_q <= q;
end process;
end Behavioral;
the package:
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
package my_data_types is
type matrix2D is array (integer range <> , integer range <> ) of signed(2 downto 0); -- Matrix2D
constant NUMBITS : integer := 3;
constant NUM_TRAIN_PATTERN : natural := 3;
end my_data_types;
A few thing stand out...
First of all, whenever you create a state machine, there needs to be a way to reset it, ideally an input signal which forces the sequential elements to a known state. In your case, there is no way to reset pr_state, and thus no way to know from the code what the starting state should be. Also, avoid "resetting" sequential elements by assigning a default value as is done for s_flipflop_adder, because that is likely to lead to a mismatch between simulation and actual implementation.
Second, do not generate sequential and combinatorial signals inside the same process. For each signal, decide if it is sequential (i.e. a flip flop, updated on a clock edge), or combinatorial (i.e. updated almost instantly from the value of other signals, slowed down only by the propagation delays in the logic elements). For sequential signals, create a sequential process in which everything is inside an if rising_edge(clk) or if clk'event and clk = '1' statement (equivalent for most purposes), and with only the clock (and maybe your reset signal, if it is asynchronous) in the sensitivity list. For combinatorial signals, put them in a combinatorial process, which is a process with no clock and a complete sensitivity list.
In your design, the first process is a proper sequential process. The second process, however, starts as a combinatorial process (with an incomplete sensitivity list), but then there is a sequential assignment to s_flipflop_adder nested in a branch of the case statement. The signal s_flipflop_adder is unlikely to ever be assigned because clk is not in the sensitivity list, and even if it was, the synthesis tools will likely not interpret that mix as you intended it.
Finally, do not use a variable to keep state information as you do with the cnt variable, and make sure you update your state only on a clock edge (i.e. sequentially).
With these three points in mind, the state machine will look something more akin to this (I inlined the definitions from the my_data_types package only to make the answer easier to read):
library ieee;
use ieee.std_logic_vector_1164.all;
use ieee.std_logic_arith.all;
entity state_machine2 is
port(
clk : in std_logic;
rst : in std_logic;
pattern : in std_logic_vector(0 to NUMBITS-1);
result : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1) );
end state_machine2;
architecture Behavioral of state_machine2 istype state is (zero , one, two);
constant NUMBITS : integer := 3;
constant NUM_TRAIN_PATTERN : natural := 3;
subtype signed3 is signed(NUMBITS-1 downto 0);
type matrix2D is array (integer range <> , integer range <> ) of signed3;
signal pr_state : state;
signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
signal cnt : integer;
begin
process(clk) is
variable add_operand : signed3;
begin
if rising_edge(clk) then
if rst = '1' then
pr_state <= zero;
cnt <= -1;
s_flipflop_adder <= (others => (others => (others => '0')));
else
case pr_state is
when zero =>
cnt <= cnt + 1;
if cnt < NUM_TRAIN_PATTERN then
pr_state <= one;
else
pr_state <= two;
end if;
when one =>
for i in 0 to NUMBITS-1 loop
for j in 0 to NUMBITS-1 loop
if i = j then
add_operand := (others => '0');
elsif pattern(i) = pattern(j) then
add_operand := (0 => '1', others => '0');
else
add_operand := (others => '1');
end if;
s_flipflop_adder(i,j) <= s_flipflop_adder(i,j)
+ add_operand;
end loop;
end loop;
when two =>
result <= s_flipflop_adder;
end case;
end if;
end if;
end process;
end Behavioral;
Thank you for posting this question, as these are very common mistakes.