I have a very basic problem. I have a clock, a counter, and a signal indicating that two other signals, which are routed to outputs in the final implementation on an FPGA, should change.
My problem is that when I simulate the following testbench, the cs_a_o
and cs_g_o
are driven to 'X' rather than '0'. When the problem started I was driving the signal several places, but I can't see how the code can be simpler, given it must be in processes (final implementation will handle serial communication)
In my efforts to solve the problem I've made a new signal, can
, which does the same as cs_X_o
does and at the same time - except it isn't in the port map since it is an internal signal. I don't understand why one signal does as expected, while the other two aren't, even though they are subject to the same manipulations in the code.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT test
PORT(
clk : IN std_logic;
CS_A_O : out std_logic;
CS_G_O : out std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
--Outputs
signal counter : integer range 0 to 125000 := 0;
signal counter_next : integer range 0 to 125000 := 0;
signal CS_A_O : std_logic := '1';
signal CS_G_O : std_logic := '1';
signal cs : std_logic := '1';
signal can : std_logic := '1';
-- Clock period definitions
constant clk_period : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: test PORT MAP (
clk => clk,
CS_A_O => CS_A_O,
CS_G_O => CS_G_O
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
counter_process : process (clk) begin
if (rising_edge(clk)) then
counter <= counter_next;
counter_next <= counter_next + 1;
if (counter = 199) then
counter <= 0;
counter_next <= 1;
cs <= not cs;
end if;
end if;
end process;
switching : process(clk) begin
if (rising_edge(clk)) then
if cs = '1' and can = '1' then
can <= not can; -- this does as expected
cs_a_o <= not cs_a_o; -- this doesn't work
elsif cs = '0' and can = '0' then
can <= not can; -- this does as expected
cs_g_o <= not cs_g_o; -- this doesn't work
end if;
end if;
end process;
ASSERT ((CS_A_O = '1' or CS_A_O = '0')
and (CS_G_O = '1' or CS_G_O = '0'))
report "It's dead wrong. CS_A_O = " & std_logic'image(CS_A_O) &
" CS_G_O = " & std_logic'image(CS_G_O)
severity error;
END;
You have two drivers for cs_a_o
and cs_g_o
. First there's the instantiation of component test
with the label uut
. Then there's your process switching
.
Try commenting out uut
:
-- Instantiate the Unit Under Test (UUT)
-- uut: test PORT MAP (
-- clk => clk,
-- CS_A_O => CS_A_O,
-- CS_G_O => CS_G_O
-- );
Any concurrent statement assigning a signal creates a driver. The value of all drivers for resolved types contribute to the effective value. In the package body std_logic_1164 you can find the resolution table and resolution function for std_logic.