How to go through multiple input combinations with a for loop in a testbench VHDL? - vhdl

I'm new to VHDL and I'm writing a test bench for an XNOR gate. The simple solution was to manually go through each combination of the two inputs but with more inputs this will take too long. How can I write this as a for loop in VHDL?
process
begin
p0 <= '1';
p1 <= '0';
wait for 1 ns;
if (pout = '1') then
error <= '1';
end if;
wait for 200 ns;
p0 <= '1';
p1 <= '1';
wait for 1 ns;
if (pout = '0') then
error <= '1';
end if;
wait for 200 ns;
p0 <= '0';
p1 <= '1';
wait for 1 ns;
if (pout = '1') then
error <= '1';
end if;
wait for 200 ns;
p0 <= '0';
p1 <= '0';
wait for 1 ns;
if (pout = '0') then
error <= '1';
end if;
wait for 200 ns;
end process;

If p0 and p1 are inputs to the device under test and their base type is compatible with the element type of type unsigned:
library ieee;
use ieee.std_logic_1164.all;
entity xnor2 is
port (
p0: in std_logic;
p1: in std_logic;
pout: out std_logic
);
end entity;
architecture foo of xnor2 is
begin
pout <= not (p0 xor p1);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity inputs is
end entity;
architecture foo of inputs is
signal p0, p1, pout: std_logic;
signal error: std_logic := '0';
begin
DUT:
entity work.xnor2
port map (
p0 => p0,
p1 => p1,
pout => pout
);
process
use ieee.numeric_std.all; -- for example, if not already visible
variable elements: unsigned (1 downto 0);
begin
elements := (others => '0');
for i in 0 to 2 ** elements'length - 1 loop
p0 <= elements(0);
p1 <= elements(1);
wait for 1 ns;
report LF & "i = " & integer'image(i) &
LF & HT & "p0 = " & std_ulogic'image(p0) &
" p1 = " & std_ulogic'image(p1) &
" error = " & std_ulogic'image(error);
if pout = '0' then
error <= '1';
end if;
wait for 200 ns;
elements := elements + 1;
end loop;
wait;
end process;
end architecture;
Which reports:
ghdl -r inputs
inputs.vhdl:45:13:#1ns:(report note):
i = 0
p0 = '0' p1 = '0' error = '0'
inputs.vhdl:45:13:#202ns:(report note):
i = 1
p0 = '1' p1 = '0' error = '0'
inputs.vhdl:45:13:#403ns:(report note):
i = 2
p0 = '0' p1 = '1' error = '1'
inputs.vhdl:45:13:#604ns:(report note):
i = 3
p0 = '1' p1 = '1' error = '1'
Where we also see error has no obvious meaning.
Without providing a minimal, complete, and verifiable example in the question there's some risk an answer may have one or more errors and future readers can't as easily verify the solution.
The idea here is to use a binary representing counter with as many bits (elements) as inputs and assign the value of bits (elements) to respective inputs in each loop iteration.
That binary value can also be provided directly from the integer value of the loop parameter. See How to easily group and drive signals in VHDL testbench which also uses aggregate assignment:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity agg_assign is
end entity;
architecture foo of agg_assign is
signal A, B, C: std_logic;
begin
process
begin
wait for 10 ns;
for i in 0 to 7 loop
(A, B, C) <= std_logic_vector(to_unsigned(i, 3));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
You can also create a record subtype to mix element and array assignments:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity aggr_rec_assign is
end entity;
architecture foo of aggr_rec_assign is
signal A, B, C: std_logic;
signal D: std_logic_vector (2 downto 0);
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
process
type inputs_rec is
record
A: std_logic;
B: std_logic;
C: std_logic;
D: std_logic_vector (2 downto 0);
end record;
variable elements: unsigned (5 downto 0);
begin
wait for 10 ns;
for i in 0 to 2 ** elements'length - 1 loop
elements := to_unsigned(i, elements'length);
(A, B, C, D) <=
inputs_rec'(
elements(5),
elements(4),
elements(3),
std_logic_vector(elements(2 downto 0))
);
wait for 10 ns;
report LF & HT & "i = "& integer'image(i) & " (A, B, C, D) = " &
std_ulogic'image(A) & " " &
std_ulogic'image(B) & " " &
std_ulogic'image(C) & " " &
to_string(D);
end loop;
wait;
end process;
end architecture;
where in both cases the aggregate assignment would be the place to select the order inputs are extracted from the binary value.

Related

procedure in VHDL returns unknown

I have to compare functional and rtl codes. The following code is written as a structural code for twoscomponent of a 16 bit input. I have tried to code the following circuit:
Here I have enclosed the code and the test-bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity two_s_complement_16bit_rtl is
Port ( A : in STD_LOGIC_VECTOR (15 downto 0);
Cout : out STD_LOGIC_VECTOR (15 downto 0):= (others => '0'));
end two_s_complement_16bit_rtl;
architecture Behavioral of two_s_complement_16bit_rtl is
procedure two_s_complement (
A : in std_logic;
B : in std_logic;
C : out std_logic;
cout : out std_logic;
cin : in std_logic) is
begin
cout := ((not A) and B) xor (((not A) xor B) and cin);
end procedure;
begin
process (A)
variable temp_C, temp_Cout: STD_LOGIC_VECTOR(15 downto 0);
constant B_0 : STD_LOGIC := '1';
constant B_1 : STD_LOGIC := '0';
begin
for i in 0 to 15 loop
if (i = 0) then
two_s_complement ( A(i), B_0 ,temp_C(i) ,temp_Cout(i) , B_1);
else
two_s_complement ( A(i), B_1 ,temp_C(i) ,temp_Cout(i) , temp_C(i-1));
end if;
end loop;
Cout <= temp_Cout;
end process;
end Behavioral;
The test-bench:
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;
entity two_s_complement_16bit_rtl_tb is
end;
architecture bench of two_s_complement_16bit_rtl_tb is
component two_s_complement_16bit_rtl
Port ( A : in STD_LOGIC_VECTOR (15 downto 0);
Cout : out STD_LOGIC_VECTOR (15 downto 0):= (others => '0'));
end component;
signal A: STD_LOGIC_VECTOR (15 downto 0);
signal Cout: STD_LOGIC_VECTOR (15 downto 0):= (others => '0');
begin
uut: two_s_complement_16bit_rtl port map ( A => A,
Cout => Cout );
stimulus: process
begin
-- Put initialisation code here
A <= "0100010010110000";
wait for 10 ns;
A <= "0011000011110111";
wait for 10 ns;
A <= "0000000000000001";
wait for 10 ns;
A <= "0011110010110011";
wait for 10 ns;
A <= "0010000100100001";
wait for 10 ns;
A <= "0001011100100011";
wait for 10 ns;
A <= "1011000110111001";
wait for 10 ns;
A <= "0000001011001010";
wait for 10 ns;
A <= "0011110110100000";
wait for 10 ns;
A <= "0100000111111000";
wait for 10 ns;
A <= "1011111001111100";
wait for 10 ns;
A <= "1111000110000001";
wait for 10 ns;
A <= "0111000111001011";
wait for 10 ns;
A <= "1011011101101010";
wait for 10 ns;
A <= "1111001001010111";
wait for 10 ns;
-- Put test bench stimulus code here
wait;
end process;
end;
I have considered three inputs for the first unit, but two of them Cin and B have their constant values as mentioned in the code, but the output is unknown.
There are three apparent errors.
First the two_s_complement procedure does not assign C which is easy to fix:
procedure
two_s_complement (
a: in std_logic;
b: in std_logic;
c: out std_logic;
cout: out std_logic;
cin: in std_logic
) is
variable inta: std_logic := not a;
begin
c := inta xor b xor cin; -- ADDED
cout := ((not a) and b) xor (((not a) xor b) and cin);
-- cout := (inta and b) or (inta and cin);
end procedure;
This is shown as a full adder with the a input inverted.
Second, you've got an incorrect association for cin in the procedure calls:
for i in 0 to 15 loop
if i = 0 then
two_s_complement (
a => a(i),
b => b_0,
c => temp_c(i),
cout => temp_cout(i),
cin => b_1
);
else
two_s_complement (
a => a(i),
b => b_1,
c => temp_c(i),
cout => temp_cout(i),
cin => temp_cout(i - 1) -- WAS temp_c(i-1)
);
end if;
The error stands out when you use named association.
Third the cout output of two_s_complement_16bit_rtl should be assigned from temp_c:
cout <= temp_c; -- WAS temp_cout;
Fixing these three things gives:
something that looks right.
The two's complement can be simplified by delivering not A to an increment circuit where all the unneeded gates are streamlined along with eliminating the B input. You'd find for instance that the LSB is never affected.

Output stays the same value

My PRN-Generator is not working. I want to do it with a linear feedback shift register.
The simulation and compiling are working without problems, but the output is wrong (lfsr_out = '0') and is not changing.
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity lfsr_counter is
generic(
WIDTH : integer := 10
);
port(
clk : in std_logic; --clock
rst : in std_logic; --positiv rst
lfsr_out : out std_logic --1 bit output of lfsr
);
end lfsr_counter;
-------------------------------------------------------------------
architecture behavioral of lfsr_counter is
type state_type is (state_rst, state_go); --rst: reset; go: lfsr
shifts
signal present_state : state_type;
signal next_state : state_type;
signal lfsr : std_logic_vector((WIDTH - 1) downto 0) :=
(others => '0');
signal d0 : std_logic := '0';
--stores the current feedbackvalue
begin
--sequencial logic:
-------------------------------------------------------------------
state_register : process(clk, rst)
begin
if (rst = '1') then
present_state <= state_rst; --default state on reset.
elsif (rising_edge(clk)) then
present_state <= next_state; --state change
end if;
end process;
-- combinatorial logic
-------------------------------------------------------------------
comb_logic : process(present_state, rst)
begin
case present_state is
when state_rst =>
if (rst = '1') then
next_state <= state_rst;
else
next_state <= state_go;
end if;
when state_go =>
if (rst = '1') then
next_state <= state_rst;
else
next_state <= state_go;
end if;
end case;
end process;
output_logic : process(present_state)
begin
if (present_state = state_go) then
--assert ((WIDTH >= 3) and (WIDTH <= 10))
--report "Error: the LFSR width must be between 3 and 10" severity
failure;
case WIDTH is --definitions for the feedback
when 3 => d0 <= lfsr(2) xnor lfsr(1);
when 4 => d0 <= lfsr(3) xnor lfsr(2);
when 5 => d0 <= lfsr(4) xnor lfsr(2);
when 6 => d0 <= lfsr(5) xnor lfsr(4);
when 7 => d0 <= lfsr(6) xnor lfsr(5);
when 8 => d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor
lfsr(3);
when 9 => d0 <= lfsr(8) xnor lfsr(4);
when 10 => d0 <= lfsr(9) xnor lfsr(6);
when others => null;
end case;
lfsr <= std_logic_vector(unsigned(lfsr) sll 1); --shifting all
bits to left by 1
lfsr_out <= lfsr(WIDTH - 1); --MSB to output
lfsr <= lfsr(WIDTH - 1 downto 1) & d0; --concatenate the
feedback to the lfsr
else
lfsr <= (others => '0'); --reset state -> lfsr contains only
'0'
lfsr_out <= '0';
end if;
end process;
end architecture;
If you set "lfsr_out <= '1'" in output_logic, the output will stay '1'. What's wrong with my code?
What's wrong with my code?
Your shift register with a value of all '0's and XNOR will produce an output d0 of '1'. This is where the '1' comes from.
You could use a generate statement to produced d0 instead of a process statement with a case statement.
The first assignment to lfsr will have no effect and can be removed. There's only one projected output waveform for any scheduled time. An assignment without an after delay will incur a delta cycle. Two of those in the same delta cycle and the last one will take effect. As a consequence you don't need packages std_logic_unsigned (Synopsys) or numeric_std (IEEE).
Synthesized results
lfsr is not a clocked register, it's a combinatorial loop always producing '1' in synthesized hardware. That's caused by a lack of sequential shifting.
Also, how would your simulation be working without problems? Process output_logic will only resume for an event on present_state.
Throwing away the separate state machine and implementing a clocked lfsr shift register and using generate statements:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.numeric_std.all;
entity lfsr_counter is
generic (
-- WIDTH: integer := 10
WIDTH: positive range 3 to 10 := 10
);
port (
clk: in std_logic;
rst: in std_logic; -- positive rst
lfsr_out: out std_logic
);
end entity lfsr_counter;
architecture behavioral of lfsr_counter is
-- type state_type is (state_rst, state_go);
-- signal present_state: state_type;
-- signal next_state: state_type;
signal lfsr: std_logic_vector((WIDTH - 1) downto 0) := (others => '0');
signal d0: std_logic := '0';
begin
-- state_register:
-- process (clk, rst)
-- begin
-- if rst = '1' then
-- present_state <= state_rst;
-- elsif rising_edge(clk) then
-- present_state <= next_state;
-- end if;
-- end process;
-- comb_logic:
-- process (present_state, rst)
-- begin
-- case present_state is
-- when state_rst =>
-- if rst = '1' then
-- next_state <= state_rst;
-- else
-- next_state <= state_go;
-- end if;
-- when state_go =>
-- if rst = '1' then
-- next_state <= state_rst;
-- else
-- next_state <= state_go;
-- end if;
-- end case;
-- end process;
-- Using VHDL -2008 you could use a case generate or elsif
WIDTH3:
if WIDTH = 3 generate
d0 <= lfsr(2) xnor lfsr(1);
end generate;
WIDTH4:
if WIDTH = 4 generate
d0 <= lfsr(3) xnor lfsr(2);
end generate;
WIDTH5:
if WIDTH = 5 generate
d0 <= lfsr(4) xnor lfsr(2);
end generate;
WIDTH6:
if WIDTH = 6 generate
d0 <= lfsr(5) xnor lfsr(4);
end generate;
WIDTH7:
if WIDTH = 7 generate
d0 <= lfsr(6) xnor lfsr(5);
end generate;
WIDTH8:
if WIDTH = 8 generate
d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3);
end generate;
WIDTH9:
if WIDTH = 9 generate
d0 <= lfsr(8) xnor lfsr(4);
end generate;
WIDTH10:
if WIDTH = 10 generate
d0 <= lfsr(9) xnor lfsr(6);
end generate;
-- output_logic:
-- process (present_state)
-- begin
-- if present_state = state_go then
-- case WIDTH is
-- when 3 =>
-- d0 <= lfsr(2) xnor lfsr(1);
-- when 4 =>
-- d0 <= lfsr(3) xnor lfsr(2);
-- when 5 =>
-- d0 <= lfsr(4) xnor lfsr(2);
-- when 6 =>
-- d0 <= lfsr(5) xnor lfsr(4);
-- when 7 =>
-- d0 <= lfsr(6) xnor lfsr(5);
-- when 8 =>
-- d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3);
-- when 9 =>
-- d0 <= lfsr(8) xnor lfsr(4);
-- when 10 =>
-- d0 <= lfsr(9) xnor lfsr(6);
-- when others =>
-- null;
-- end case;
-- -- lfsr <= lfsr sll 1;
-- lfsr_out <= lfsr(WIDTH - 1);
-- lfsr <= lfsr(WIDTH - 1 downto 1) & d0;
-- else
-- lfsr <= (others => '0');
-- lfsr_out <= '0';
-- end if;
-- end process;
lfsr_reg:
process (rst, clk)
begin
if rst = '1' then
lfsr <= (others =>'0');
elsif rising_edge(clk) then
lfsr <= lfsr(WIDTH - 2 downto 0) & d0; -- WAS WIDTH - 1 downto 1
end if;
end process;
lfsr_out <= lfsr(WIDTH - 1); -- not separately registered
end architecture;
The bit with the generate statement(s) does nothing interesting but offload work from synthesis, which would have to gate eat all those assignments in the case statement multiplexer.
Also with an added testbench to create a Minimal, Complete and Verifiable example we see lfsr doesn't actually shift left. The fix is shown in the code above and involves a change:
lfsr <= lfsr(WIDTH - 2 downto 0) & d0; -- WAS WIDTH - 1 downto 1
The testbench:
library ieee;
use ieee.std_logic_1164.all;
entity lfsr_counter_tb is -- a testbench
end entity;
architecture foo of lfsr_counter_tb is
constant WIDTH: positive range 1 to 10 := 10; -- test full length
signal clk: std_logic := '1';
signal rst: std_logic := '0';
signal lfsr_out: std_logic;
begin
DUT:
entity work.lfsr_counter
generic map (
WIDTH => WIDTH
)
port map (
clk => clk,
rst => rst,
lfsr_out => lfsr_out
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > 550 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 11 ns;
rst <= '1';
wait for 99 ns;
rst <= '0';
wait;
end process;
end architecture;
simulates:
And lfsr_counter should synthesize and function as well.
Uhhm. Never heard anything about the generate statement in our Digital Design course! this could be very useful in some cases. Thank you for this example. I understand your code. It is really simple and self-explaining. You can also avoid combinatorial loops. However, it is a different approach. I still would like to implement it as a FSM and understand the mechanisms of the FSM's. Now, I know that the output_logic part is not clocked and that this causes the comb. loop. Also that only the last statement of lfsr is being executed. What do I have to edit to make it work?
That as they say is a different question. A twofer special, today only.
Your code displays programming language thinking while VHDL is a hardware description language. For instance no signal update occurs while any process has yet to resume or subsequently suspend in the current simulation cycle. This means d0 doesn't want to be a signal or it's assignments want to be in a separate process.
Signals communicate between processes. For an object that is solely used inside a process you should use a variable if the value is evaluated after assignment.
There's also the multiplexer using WIDTH to assign d0. It represents hardware that will get gate eaten during synthesis because WIDTH is unchanging, passed as a generic constant.
The generic constant can have a defined scalar range:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.numeric_std.all;
entity lfsr_counter is
generic (
-- WIDTH: integer := 10
WIDTH: positive range 3 to 10 := 10
);
port (
clk: in std_logic;
rst: in std_logic; -- positive rst
lfsr_out: out std_logic
);
end entity lfsr_counter;
This allows writing VHDL design description that doesn't have to handle values outside what you use. All the extra logic gets gate eaten but you can introduce errors.
So with d0 made a variable, WIDTH constrained and the lsfr_out assignment moved to a concurrent statement:
architecture behave of lfsr_counter is
type state_type is (state_rst, state_go);
signal present_state: state_type;
signal next_state: state_type;
signal lfsr: std_logic_vector((WIDTH - 1) downto 0) := (others => '0');
-- signal d0: std_logic := '0';
begin
state_register:
process (clk, rst)
begin
if rst = '1' then
present_state <= state_rst;
elsif rising_edge(clk) then
present_state <= next_state;
end if;
end process;
comb_logic:
process (present_state, rst)
begin
case present_state is
when state_rst =>
if rst = '1' then
next_state <= state_rst;
else
next_state <= state_go;
end if;
when state_go =>
if rst = '1' then
next_state <= state_rst;
else
next_state <= state_go;
end if;
end case;
end process;
output_logic:
process (clk) -- (present_state)
variable d0: std_logic;
begin
if rising_edge(clk) then
if present_state = state_go then
case WIDTH is
when 3 =>
d0 := lfsr(2) xnor lfsr(1);
when 4 =>
d0 := lfsr(3) xnor lfsr(2);
when 5 =>
d0 := lfsr(4) xnor lfsr(2);
when 6 =>
d0 := lfsr(5) xnor lfsr(4);
when 7 =>
d0 := lfsr(6) xnor lfsr(5);
when 8 =>
d0 := lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3);
when 9 =>
d0 := lfsr(8) xnor lfsr(4);
when 10 =>
d0 := lfsr(9) xnor lfsr(6);
-- when others =>
-- null;
end case;
-- lfsr <= lfsr sll 1;
-- lfsr_out <= lfsr(WIDTH - 1);
-- lfsr <= lfsr(WIDTH - 1 downto 1) & d0;
lfsr <= lfsr(WIDTH - 2 downto 0) & d0;
else
lfsr <= (others => '0'); -- a synchronous reset
-- lfsr_out <= '0';
end if;
end if;
end process;
lfsr_out <= lfsr(WIDTH - 1); -- not separately registered, a mux
end architecture behave;
All the changes from your first architecture are shown, original code commented out. This analyzes, elaborates and simulates with the same testbench and produces the same results.
The reason for moving the lfsr_out assignment is based on the same issue as d0, with another observation. The output_logic process will only resume execution when there is an event on a signal found the sensitivity list.
This would mean you would miss transitions on lfsr_out simulating your first design, or would imply a half clock delay (for the next clk edge) using a clocked lfsr register as in the above behave architecture.
You could note the lsfr assignment change to actually provide a shift as in the lfsr_reg process in the top code example. You'll note that first assignment to lfsr is still commented out.

Why won't VHDL left shifter work?

I'm new to VHDL and I'm trying to write a left shifter that takes in a 32 bit value and a 5 bit value. The left shifter then tries to perform a logical left shift of the 32 bit value by moving out the number of bits specified by the 5 bit number on the left and bringing that many zeros on the right. I can't understand why the array notation isn't working. The result of 1 << 1 produces 20000000 instead of 00000002. Can someone explain where I'm going wrong? Here's the code:
SIGNAL lshiftOutput : STD_LOGIC_VECTOR( 31 downto 0 );
COMPONENT Lshift32
Port( a : in STD_LOGIC_VECTOR( 31 downto 0 );
b : in STD_LOGIC_VECTOR( 4 downto 0 );
lshiftOutput : out STD_LOGIC_VECTOR( 31 downto 0 ) );
END COMPONENT;
PROCESS( a, b, opcode, adderOutput, subtractOutput, xorOutput, lshiftOutput, rshiftOutput )
BEGIN
IF opcode = "0000" THEN
result <= x"00000000";
ELSIF opcode = "0001" THEN
result <= adderOutput;
ELSIF opcode = "0010" THEN
result <= subtractOutput;
ELSIF opcode = "0011" THEN
result <= NOT a;
ELSIF opcode = "0100" THEN
result <= a AND b;
ELSIF opcode = "0101" THEN
result <= a OR b;
ELSIF opcode = "0110" THEN
result <= xorOutput;
ELSIF opcode = "0111" THEN
result <= lshiftOutput;
ELSIF opcode = "1000" THEN
result <= rshiftOutput;
END IF;
END PROCESS;
LIBRARY ieee;
USE ieee.std_logic_unsigned.ALL;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY Lshift32 IS
Port( a : in STD_LOGIC_VECTOR ( 31 downto 0 );
b : in STD_LOGIC_VECTOR ( 4 downto 0 );
lshiftOutput : out STD_LOGIC_VECTOR ( 31 downto 0 ) );
END Lshift32;
ARCHITECTURE Lshift32Architecture of Lshift32 IS
BEGIN
PROCESS( a, b )
VARIABLE shiftAmount : INTEGER := 0;
BEGIN
shiftAmount := to_integer( b(4 downto 0) );
-- Shift left
lshiftOutput <= a( 31-shiftAmount downto 0 ) & ( shiftAmount-1 downto 0 => '0' );
END PROCESS;
END Lshift32Architecture;
The test bench for this is:
-- Shift Left -------------------------------------------------------
WAIT FOR 9 ns;
op <= "0111";
-- 1 << 1
input_a <= x"00000001";
input_b <= x"00000001";
WAIT FOR 1 ns;
IF (output /= x"00000002") THEN
ASSERT false REPORT "1 << 1 has incorrect result" severity error;
END IF;
Brian asked that you supply a Minimal, Complete, and Verifiable example, your edited code doesn't do that. And the reason for asking is that it's possible to create an mcve around the portions of your code you originally supplied that does give the right answer:
library ieee; -- added
use ieee.std_logic_1164.all; -- added
use ieee.numeric_std_unsigned.all; -- added
entity lshift32 is
port( a : in std_logic_vector ( 31 downto 0 );
b : in std_logic_vector ( 4 downto 0 );
lshiftoutput : out std_logic_vector ( 31 downto 0 ) );
end entity lshift32;
architecture lshift32architecture of lshift32 is
begin
process( a, b )
variable shiftamount : integer := 0;
begin
shiftamount := to_integer( b(4 downto 0) );
-- shift left
lshiftoutput <= a( 31-shiftamount downto 0 ) & ( shiftamount-1 downto 0 => '0' );
end process;
end architecture lshift32architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity lshift32_tb is
end entity;
architecture foo of lshift32_tb is
signal a: std_logic_vector (31 downto 0) := (others => '0');
signal b: std_logic_vector (4 downto 0) := (others => '0');
signal lshiftoutput: std_logic_vector (31 downto 0);
begin
DUT:
entity work.lshift32
port map (
a => a,
b => b,
lshiftoutput => lshiftoutput
);
SIMULIS:
process
begin
wait for 10 ns;
a(0) <= '1'; -- 1
b(0) <= '1'; -- 1
wait for 10 ns;
wait;
end process;
ANALYSIS:
process (lshiftoutput)
variable shiftamount: integer;
begin
if now > 0 ns then
shiftamount := to_integer(b);
report "ShiftAmount = " & integer'image(shiftamount);
report "lshiftOutput = " & to_string(lshiftoutput);
end if;
end process;
end architecture;
And running the above testbench gives:
ghdl -a --std=08 lshift.vhdl
ghdl -e --std=08 lshift32_tb
ghdl -r lshift32_tb
lshift.vhdl:60:13:#10ns:(report note): ShiftAmount = 1
lshift.vhdl:61:13:#10ns:(report note): lshiftOutput = 00000000000000000000000000000010
And that your execution fails says there's either something wrong with your context clause (use clauses) or something wrong with your testbench.
Note that you are using both none standard package std_logic_unsigned and IEEE standard package numeric_std. You really shouldn't mix and match there can be unexpected consequences.
The package numeric_std_unsigned is available with a VHDL implementation compliant with the IEEE Std 1076-2008 standard. If using a previous version of the VHDL standard you can use package numeric_std and type convert b to unsigned as the expression passed to to_integer.
For the testbench supplied with this answer you'd also find that to_stringfor std_logic_vector is not supplied. Without seeing your entire testbench it could well be functional.
If you want to prove the answer supplied testbench works in a non -2008 revision environment:
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
The function can be supplied as an architecture declarative item.

How to model two D flip-flops with multiplexing logic

I would like to model two D flip-flops using a multiplexer for some logic. I want to have static outputs of "000" for the three MSB when the multiplexer selects DFF D1 (B = 0) and the three LSB should be fixed to "111" when the multiplexer selects DFF D2 (B = 1).
This is my code -- which I originally typed blindly without checking for obvious syntax errors -- below. I don't know how to solve my problem:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity dff_mux is
Port ( D1, D2 : in STD_LOGIC_VECTOR(11 DOWNTO 0);
clk : in STD_LOGIC;
rst : IN STD_LOGIC;
B : in STD_LOGIC;
data : out STD_LOGIC_VECTOR(11 DOWNTO 0));
end dff_mux;
architecture Behavioral of dff_mux is
signal Q1, Q2 : std_logic_vector(11 downto 0);
begin
process(clk,rst)
begin
if (rst = '1') then
Q1<="000000000000";
elsif (clk'event and clk='1') then
if (B = '0') then
-- I want to fix thee MSB to "000"
-- other bits shall retain their input value
D1(11) <= '0';
D1(10) <= '0';
D1(9) <= '0';
Q1 <= D1;
elsif (B = '1') then
-- fix three LSB to "111"
-- other bits retain their input value
D2(2) <= '1';
D2(1) <= '1';
D2(0) <= '1';
Q2 <= D2;
end if;
end if;
end process;
-- MUX description: select D1 when B = 0, else select D2 when B = 1
MUX : process(B)
begin
data <= Q1 when (B = '0') else
Q2;
end process MUX;
end Behavioral;
Thanks in advance to anybody who can help me.
There are numerous errors in your VHDL design description. The two process statements drive the same signals (Q1 and Q2). The second process has three errors (no process statement label, while a label is specified in closing, concurrent signal assignment statements where sequential signal assignment statements are appropriate). It would appear the second process statement should be eliminated in it's entirety.
If the intent is to have a multiplexer on the inputs to the Q1,Q2 registers the first process is non-functional. You can't assign values to a formal input inside a block.
You should be assigning the B selected values to Q1 and Q2 directly inside the process statement (inside the clk elsif).
Your assignment to D(11) is defective (uses == instead of <=).
It isn't a multiplexer if you only assign one value to a particular signal (e.g. longest static prefix D1 and D2). Note there is no reset value for Q2 provided.
There is no place data is assigned.
If you're doing this for class work there is little benefit in someone providing the answer without learning VHDL a bit more. If you're earnestly trying to learn VHDL you need more and incrementally building exercises.
If I understand what you are trying to do correctly it would look something like this:
architecture Behavioral of basculeD is
-- signal Q1, Q2 : std_logic_vector(11 downto 0);
begin
-- process(clk,rst)
-- begin
-- if (rst='1') then Q1<="000000000000";
-- elsif ( clk'event and clk='1') then
-- if (B='0') then
-- D1(11) =='0'; -- i want to fix the 3MSB of D1 in the "000" ...
-- D1(10) <='0';
-- D1(9) <='0';
-- Q1<= D1;
-- elsif (B='1') then
-- D2(2)<= '1'; -- the 3LSB are fixed to 111 , and defaut value ...
-- D2(1)<='1';
-- D2(0)<='1';
-- Q2<=D2;
-- end if;
-- end if;
-- end process;
-- description MUX : select D1 when B=0, else select D2 when B= 1
-- process( B)
-- begin
-- Q1 <= D1 when B='0' else
-- Q2<=D2 when B='1' ;
-- end process MUX;
MUXED_REG:
process (clk,rst)
begin
if rst = '1' then
data <= (others => '0'); -- equivalent to "000000000000"
elsif clk'event and clk = '1' then
-- the actual multiplexer:
if B = '0' then
data <= ("000" & D1(8 downto 0));
else -- B = '1', or other values
data <= (D2(11 downto 3) & "111");
end if;
end if;
end process;
end Behavioral;
You could of course retain an intermediary signal, say Q and use it in place of data above, with a concurrent signal assignment from Q to data (the output).
Using the above architecture in place of your's analyzes.
With a test bench:
library ieee;
use ieee.std_logic_1164.all;
entity basculeD_test is
end entity;
architecture test of basculeD_test is
component basculeD is
port (
d1, d2: in std_logic_vector(11 downto 0);
clk: in std_logic;
rst: in std_logic;
b: in std_logic;
data: out std_logic_vector(11 downto 0)
);
end component;
signal d1: std_logic_vector(11 downto 0) := (others => '1');
signal d2: std_logic_vector(11 downto 0) := (others => '0');
signal clk: std_logic := '0';
signal rst: std_logic := '1';
signal b: std_logic := '0';
signal data: std_logic_vector(11 downto 0);
begin
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 100 ns then
wait;
end if;
end process;
RESET:
process
begin
wait for 31 ns;
rst <= '0';
wait;
end process;
DUT:
basculeD
port map (
d1 => d1,
d2 => d2,
clk => clk,
rst => rst,
b => b,
data => data
);
STIMULUS:
process
begin
wait for 65 ns;
b <= '1';
wait;
end process;
end architecture;
And using the replacement architecture for basculeD with the MUXED_REG process:
david_koontz#Macbook: ghdl -a basculeD.vhdl
david_koontz#Macbook: ghdl -e basculeD_test
david_koontz#Macbook: ghdl -r basculeD_test --wave=basculeD_test.ghw
david_koontz#Macbook: open basculeD_test.gtkw (previously saved save file)
Gives:
There's of course the possibility that you are trying to separate storage from multiplexing entirely, which says you could use Q1 and Q2 as registers (and only need 9 bits), a separate multiplexer (as implied in your original basculeD architecture) allowing B to steer between modified Q1 and Q2 register values on output data.
That would look something like this:
architecture Behavioral of basculeD is
signal Q1: std_logic_vector(8 downto 0);
signal Q2: std_logic_vector(11 downto 3);
begin
REGS:
process (clk, rst)
begin
if rst = '1' then
Q1 <= (others => '0');
Q2 <= (others => '0');
elsif clk'event and clk = '1' then
Q1 <= D1 (8 downto 0);
Q2 <= D2(11 downto 3);
end if;
end process;
MUX:
process (B,Q1,Q2)
begin
if B = '0' then
data <= ("000" & Q1);
else
data <= (Q2 & "111");
end if;
end process;
And give you something like this:
VHDL is meant to convey a design specification to the reader, which is made easier when using some convention for capitalization (VHDL isn't case sensitive except in extended identifiers) and indentation.
Welcome to StackOverflow! First off, this is an English Question & Answer site. Please translate all pertinent terms into English, i.e. basculeD => D flip-flop etc. Also, try to describe your problem the best you can without too many spelling mistakes (spell check!) or grammar errors. This will help other people understand you and help you efficiently.
Anyway, your main problem is, that you have input ports D1 and D2 and you try to write to them. Instead, you should just take whatever bits you need and disregard the other bits.
Instead of trying to write to the input, which is not possible, you should try this:
Q2 <= D2(11 downto 3) & "111";
This statement takes bits 11 through 3 from D2 and assigns them to bits 11 through 3 of Q2. Bits 2 through 0 of Q2 are assigned a constant value of "111".
You should remember that you cannot "re-write" input port values. Your last process could also be re-written to a parallel statement.
Also, your design is peculiar in the sense that you want to store the modified value separately.
Consider this:
D1 = x"00A"; D2 = x"00B", B = '0', clk --> rising edge
Now, Q1 = x"00A", Q2 = x"???", data = Q1 = x"00A", B = '0', clk = '1'
Now, Q1 = x"00A", Q2 = x"???", data = Q2 = x"???", B = '1', clk = '1'
You need at least two clock periods to switch your outputs when you want to switch between B = '1' and B = '0', because Q1 resp Q2 will hold old (and possibly uninitialized) values.
Your design might not do what you want it to do. If you want a multiplexer, go for a multiplexer. If you want a flip flop, build a flip flop.
process(clk,rst)
begin
if (rst = '1') then
data <= (others => '0');
elsif (clk'event and clk='1') then
if (B = '1') then
-- Select D2
data <= D2(11 downto 3) & "111";
else
-- Select D1
data <= "000" & D1(8 downto 0);
end if;
end if;
end process;
You might also want to think about whether a reset is really appropriate and whether a synchronous reset might be more beneficial.

VHDL simulation won't run

I have just picked up The Designer's Guide to VHDL and I am working through the exercises in the first chapter. I ran into an issue with my 2 bit multiplexer that I don't understand.
The code for my multiplexer:
library ieee;
use ieee.std_logic_1164.all;
entity multi2 is
port
(
a,b : in bit;
sel : in boolean;
z : out bit
);
end multi2;
architecture behave of multi2 is
begin
storage : process is
variable stored_d0 : bit;
begin
wait for 1 ns;
if sel then
z <= a;
else
z <= b;
end if;
end process storage;
end architecture behave;
I can't figure out why I need the "wait for 1 ns;" line. If I move it to below the "end if" line the simulation won't work and I won't get my .vcd output from GHDL. Without the wait line, or it being in the wrong spot gives me an error in my vcd file about beginning and end time being the same.
Do I need wait statements in my process in order to work?
My test bench code is below:
library ieee;
use ieee.std_logic_1164.all;
entity multi2_tb is
end multi2_tb;
architecture test of multi2_tb is
component multi2
port
(
a,b : in bit;
sel : in boolean;
z : out bit
);
end component;
signal a,b : bit;
signal sel : boolean;
signal z : bit;
begin
multiplexer2: multi2 port map (a => a, b => b, sel => sel, z => z);
process begin
a <= '0';
b <= '1';
sel <= false;
wait for 3 ns;
a <= '0';
b <= '1';
sel <= true;
wait for 3 ns;
a <= '0';
b <= '1';
sel <= false;
wait for 3 ns;
assert false report "Reached end of test";
wait;
end process;
end test;

Resources