Not understanding vhdl online compiler error - vhdl

i am using an inline compiler (https://www.edaplayground.com/) and im not understanding the online compilers error message. I am trying to build the boolean expression (a * !b) + (b * !c) + (!b * c).
My code is:
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY (MySimp) IS
PORT (A: in STD_LOGIC;
B: in STD_LOGIC;
C: in STD_LOGIC;
Z: out STD_LOGIC;
);
End MySimp;
ARCHITECTURE (details) OF (MySimp) IS
BEGIN
PROCESS
VARIABLE D, E, F: STD_LOGIC;
BEGIN
IF A AND (NOT B)= '1' THEN D:= '1';
ELSE D:= '0';
END IF:
IF B AND (NOT C)= '1' THEN E:= '1';
ELSE E:= '0';
END IF:
IF C AND (NOT B)= '1' THEN F:= '1';
ELSE F:= '0';
END IF:
Z <= D OR E OR F;
END PROCESS;
END details;

As the error shows, you are compiling a VHDL file (.vhd) as a (System) Verilog file (.sv). Those are two different hardware description languages.
In the Languages and Libraries tab on the left, you need to set the Testbench + Design to VHDL.
But there's a problem in your code. The process statement doesn't have a sensitivity list. HDLs are usually parallel languages, which means you need to indicate when a process needs to be triggered: else it will try to loop indefinitely in an infinitesimal time. You either need to add a wait-statement, to stop the loop, or implicitly do that by adding the trigger signals to the process sensitivity list. e.g.
process (a,b,c)
There are more semantical issues with your code. I added them in comments
library ieee;
use ieee.std_logic_1164.all;
entity MySimp is -- no braces around the name
port (
a: in std_logic;
b: in std_logic;
c: in std_logic;
z: out std_logic -- no semicolon
);
end entity;
architecture arch of MySimp is
begin
process(a, b, c)
variable d, e, f: std_logic;
begin
if (a and (not b))= '1' then -- add braces around the logic expression
d:= '1';
else
d:= '0';
end if; -- semicolon instead of colon
-- alternative method 1
if b='1' and c='0' then
e:= '1';
else
e:= '0';
end if;
-- alternative method 2
f := c and (not b);
z <= d or e or f;
end process;
-- or replace the whole process by:
--z <= (a and (not b)) or (b xor c);
-- as (b and (not c)) or (c and (not b)) is an exclusive-or operation
end architecture;

Related

How to implement a test bench for 4x1 mux

I'm struggling to write a test bench for this:
---------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
---------------------------------------
ENTITY mux IS
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
END mux;
---------------------------------------
ARCHITECTURE pure_logic OF mux IS
BEGIN
y <= (a AND NOT s1 AND NOT s0) OR
(b AND NOT s1 AND s0) OR
(c AND s1 AND NOT s0) OR
(d AND s1 AND s0);
END pure_logic;
---------------------------------------
This is my progress so far.
I am not quite sure how to write the stimulus part.
I tried running it through a behavioral simulation, but I am getting Undefined Errors in the results.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux_tb is
-- Port ( );
end mux_tb;
architecture Behavioral of mux_tb is
component mux
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
end component;
signal a : std_logic;
signal b : std_logic;
signal c : std_logic;
signal d : std_logic;
signal s0 : std_logic;
signal s1 : std_logic;
signal y : std_logic;
begin
uut: mux port map (
a => a,
b => b,
c => c,
d => d,
s0 => s0,
s1 => s1,
y => y
);
process
begin
s0 <= '0'; s1 <= '0';
wait for 100 ns;
s1 <= '0'; s0 <= '1';
wait for 100ns;
s1 <= '1'; s0 <= '0';
wait for 100ns;
s1 <= '1'; s0 <= '1';
end process;
end Behavioral;
Could anyone explain what I am doing wrong?
Your testbench does not supply stimuli for a, b, c and d. You need to assign them as well as s0 and s1.
architecture full_behavior of mux_tb is
component mux
PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
y: OUT STD_LOGIC);
end component;
signal a : std_logic;
signal b : std_logic;
signal c : std_logic;
signal d : std_logic;
signal s0 : std_logic;
signal s1 : std_logic;
signal y : std_logic;
use ieee.numeric_std.all; -- CHANGED Added use clause
begin
uut:
mux port map (
a => a,
b => b,
c => c,
d => d,
s0 => s0,
s1 => s1,
y => y
);
STIMULI_ASSERT:
process
variable inputs: std_logic_vector (3 downto 0); -- data inputs
variable s1s0: integer range 0 to 3; -- selects as integer
begin
for i in 0 to 63 loop
(d, c, b, a, s1, s0) <= to_unsigned(i, 6);
wait for 100 ns;
inputs := (d, c, b, a);
s1s0 := to_integer(unsigned'(s1 & s0));
assert y = inputs(s1s0)
report "Expected " & std_ulogic'image(inputs(s1s0)) &
" got " & std_ulogic'image(y)
severity error;
end loop;
wait;
end process;
end architecture;
You can do this with a for loop which assigned values to all the mux inputs. Additionally if all the inputs are ordered you can use s0 and s1 to select which of the data inputs should appear on y.
Here the for loop range is determined by the power of two raised to the number of inputs.
This
(d, c, b, a, s1, s0) <= to_unsigned(i, 6);
is an aggregate assignment that takes it's type from context (the entire statement). 6 is the number of inputs and specifies the length of integer value i converted to unsigned. The assignment is to individual elements of the target aggregate.
this
inputs := (d, c, b, a);
has the type of the aggregate specified by the assignment target (std_logic_vector).
and this
s1s0 := to_integer(unsigned'(s1 & s0));
saves the integer value of the concatenation of s1 & s0 specified as type unsigned to s1s0.
The assertion checks the expected output as an indexed value of the data inputs against y and when not equal reports an error along with the expected and y values.
We use type unsigned declared in IEEE package numeric_std along with it's operations when we want to treat a composite value as an unsigned number.
You might want separate loops for the ABCD inputs and the select inputs. This makes it easier to see that the output reacts to B but not A,C,D inputs when the select is set to B, and so on. Clearer than trying to interpret a 6 bit number.
In addition to the stimulus part covered in other answers, a good TB will compute (or read from an array or file or something) the expected outputs, and compare these with the actual outputs, reporting any differences ... you can use Assert/Report for this.
If you then log Pass/Fail and number of errors (possibly to a file) at end of test, you can use this in regression tests and never have to stare at waveforms again. That's when it gets to be a time saver.
See also osvvm.org and Vunit (on github) for tools to help.
I am not quite sure how to write the stimulus part
You appear to be asking for a design technique that can be used to stimulate the inputs.
A simple method for testing a purely combinatorial circuit like your component is to drive the inputs from a test counter. In this case, it can be a 7-bit std_logic_vector counter.
Then write a loop with 128 passes. On each pass, it will perform the component's logic function on the counter value to produce an expected result. The pass will wait for the component outputs to settle then use an assert to compare the actual result with the expected result and display an error if they don't match. Then increment counter and do the next pass.

How to change to when statement

can someone help me on how to change this vhdl code to using 'when' statement?
Here is the code that I have written:
library IEEE;
use IEEE.std_logic_1164.all;
entity sel2_1 is
port( A, B, SEL : in std_logic;
outsgnl : out std_logic);
end sel2_1;
architecture EX1 of sel2_1 is
begin
outsgnl <= (not SEL and A) or (SEL and B);
end EX1;
the simulation result is as follows:
simulation
When keyword is used in different VHDL assignments. Assuming SEL is only '0' or '1' you can simpley replace
outsgnl <= (not SEL and A) or (SEL and B);
by a selected signal assignment, often referred as with/select assignment
with SEL select outsgnl <=
A when '0',
B when others;
Alternatively you may use conditional signal assignment often referred as when/else
outsgnl <= A when SEL = '0' else B;

VHDL nested case statement for some case options

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.

how can I use an infix expression in a case statement in VHDL?

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;

Binary serial adder - VHDL

I'm trying to design a 32bit binary serial adder in VHDL, using a structural description. The adder should make use of a full adder and a d-latch. The way I see it is:
Full adder:
architecture Behavioral of FullAdder is
begin
s <= (x xor y) xor cin;
cout <= (x and y) or (y and cin) or (x and cin);
end Behavioral;
D-Latch:
architecture Behavioral of dLatch is
begin
state: process(clk)
begin
if(clk'event and clk = '1') then
q <= d;
end if;
end process;
end Behavioral;
Serial adder:
add: process ( clk )
variable count : integer range 0 to 31;
variable aux : STD_LOGIC;
variable aux2 : STD_LOGIC;
begin
if(clk'event and clk = '1') then
fa: FullAdder port map(x(count), y(count), aux, s(count), aux2);
dl: dLatch port map(clock, aux2, aux);
count := count + 1;
end if;
end process;
However, it doesn't seem to work.
Also, what would be the simplest way to pipeline the serial adder?
"It doesn't seem to work" is pretty general, but one problem I see is that you are trying to instantiate the component fa: FullAdder within a process. Think about what component instantiation means in hardware, and you will realize that it makes no sense to instantiate the module on the rising_edge of clk...
Move the instantiation out of the process, and it should at least remove the syntax error you should be seeing ("Illegal sequential statement." in ModelSim).
For pipelining the serial adder, the best way is to connect the adders and d flip-flops one after the other. So, you would have the cout of the first adder be the input of a flip-flop. The output of that flip-flop will be the cin of the next adder and so on. Be careful though, because you will also have to pipeline the s of each adder, as well as each bit of the input, by essentially putting several d flip-flops in a row to copy them through the various pipeline stages.

Resources