I have been trying to make a generic sequence detector. When i try to simulate my design, I get a simulator 45-1 Fatal run time error. Can somebody please help me with this. Here is my Test bench and design.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Sequence_tb is
end Sequence_tb;
architecture Behavioral of Sequence_tb is
component sequence is
Generic(width: integer;
sequence: std_logic_vector);
Port(din,CLK,RST:in std_logic;
dout: out std_logic;
temp: buffer std_logic_vector(0 to width-1));
end component;
constant CLK_period: time := 10ns;
constant width: integer := 4;
constant sequence0: std_logic_vector(width-1 downto 0) := "1010";
signal din,CLK,RST,dout: std_logic := '0';
signal temp : std_logic_vector(0 to width-1) := (others=>'0');
begin
uut: sequence generic map(width=>width,sequence=>sequence0)
port map(din=>din,CLK=>CLK,RST=>RST,dout=>dout,temp=>temp);
CLK_proc: process
begin
CLK <= not CLK;
wait for CLK_period;
end process;
RST_proc: process
begin
RST <= '1';
wait for 20 ns;
RST <= '0';
wait;
end process;
din_proc: process
begin
din <= '1';
wait for 30 ns;
din <= '0';
wait for 10 ns;
din <= '1';
wait for 10 ns;
din <= '0';
wait for 10 ns;
din <= '1';
wait for 10 ns;
wait;
end process;
end Behavioral;
Design File:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Sequence is
Generic(width: integer;
sequence: std_logic_vector);
Port (din, CLK, rst: in std_logic;
dout: out std_logic;
temp: buffer std_logic_vector(0 to width-1));
end Sequence;
architecture Beh of Sequence is
subtype statetype is integer range 0 to width-1;
signal prstate,nxstate: statetype := 0;
begin
process(RST,CLK)
begin
if RST='1' then
temp <= (others => '0');
nxstate <= 0;
elsif CLK'event and CLK='1' then
temp(prstate) <= din;
for k in prstate downto 0 loop
if temp(k downto 0) = sequence(k downto 0) then
nxstate <= k;
exit;
else temp <= temp(1 to width-1) & '0';
end if;
end loop;
end if;
prstate <= nxstate;
end process;
dout <= '1' when prstate = width-1 and din = sequence(sequence'left) else '0';
end Beh;
Related
I have this code which is a bidirectional counter that loops around.
I now want to add an input (maybe from switches or something), which controls the maximum value of the counter, for example if the max value from the input is "0111" the counter will count up to 0111 and then loop back around to 0000, and if the counter is counting down to 0000 it will loop back to 0111. I'm getting a bit confused on how/where I should do this because I've used nested ifs to implement an enable and reset input.
Here is the code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity UPDOWN_COUNTER is
Port ( clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down
enable: in std_logic; -- enable
max: in std_logic_vector(3 downto 0); -- max value counter
counter: out std_logic_vector(3 downto 0) -- output 4-bit counter
);
end UPDOWN_COUNTER;
architecture Behavioral of UPDOWN_COUNTER is
signal counter_updown: std_logic_vector(3 downto 0);
begin
process(clk,reset,enable,max)
begin
if(enable ='1') then
if(rising_edge(clk)) then
if(reset='1') then
counter_updown <= x"0";
elsif(up_down='1') then
counter_updown <= counter_updown - x"1"; -- count down
else
counter_updown <= counter_updown + x"1"; -- count up
end if;
end if;
end if;
end process;
counter <= counter_updown;
end Behavioral;
Here is the test bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_counters is
end tb_counters;
architecture Behavioral of tb_counters is
component UPDOWN_COUNTER
Port ( clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(3 downto 0); -- max value counter
counter: out std_logic_vector(3 downto 0) -- output 4-bit counter
);
end component;
signal reset,clk,enable,up_down: std_logic;
signal max,counter:std_logic_vector(3 downto 0);
begin
dut: UPDOWN_COUNTER port map (clk => clk, reset=>reset,enable => enable, up_down => up_down, max => max,counter => counter);
-- Clock
clock_process :process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
stim_proc: process
begin
max <= "1000"; -- Test value for Counter max value
enable <= '1';
reset <= '1';
up_down <= '0';
wait for 20 ns;
reset <= '0';
wait for 300 ns;
up_down <= '1';
--
wait for 50 ns;
enable <= '0';
wait for 50 ns;
enable <= '1';
wait;
end process;
end Behavioral;
You've specified a synchronous reset. There's at least one synthesis issue, where enable is inferred to gate the clock. The numeric package has been switched to ieee.numeric_std in the following (the example can be modified for the non-standard Synopsys numeric package):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity updown_counter is
port (
clk: in std_logic;
reset: in std_logic;
up_down: in std_logic;
enable: in std_logic;
max: in std_logic_vector(3 downto 0);
counter: out std_logic_vector(3 downto 0)
);
end entity updown_counter;
architecture behavioral of updown_counter is
signal counter_updown: unsigned(3 downto 0);
begin
process (clk) -- other signals evaluated inside clock edge
begin
if rising_edge(clk) then
if enable = '1' then -- don't gate the clock
if reset = '1' then
counter_updown <= (others => '0');
elsif up_down = '1' then -- down
if counter_updown = 0 then
counter_updown <= unsigned(max);
else
counter_updown <= counter_updown - 1;
end if;
else -- count up
if counter_updown = unsigned(max) then
counter_updown <= (others => '0');
else
counter_updown <= counter_updown + 1;
end if;
end if;
end if;
end if;
end process;
counter <= std_logic_vector(counter_updown);
end architecture behavioral;
And that gives:
with your testbench.
This is the similar to #user1155120's answer (which I recommend you accept as the answer), but I've used an asynchronous reset instead. Also added a generic to specify the number bits in the counter.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity UpdownCounter is
generic
(
COUNTER_BITS: natural := 4
);
port
(
clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(COUNTER_BITS - 1 downto 0); -- max value counter
counter: out std_logic_vector(COUNTER_BITS - 1 downto 0) -- output N-bit counter
);
end UpdownCounter;
architecture V1 of UpdownCounter is
signal counter_updown: unsigned(COUNTER_BITS - 1 downto 0);
begin
process(clk, reset)
begin
if reset then
-- Do asynchronous reset.
counter_updown <= (others => '0');
elsif rising_edge(clk) then
-- Do synchronous stuff.
if enable then
if up_down then
-- Count down to zero cyclically.
if counter_updown = 0 then
counter_updown <= unsigned(max);
else
counter_updown <= counter_updown - 1;
end if;
else
-- Count up to max cyclically.
if counter_updown = unsigned(max) then
counter_updown <= (others => '0');
else
counter_updown <= counter_updown + 1;
end if;
end if;
end if;
end if;
end process;
counter <= std_logic_vector(counter_updown);
end V1;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity UpdownCounter_TB is
end UpdownCounter_TB;
architecture V1 of UpdownCounter_TB is
component UpdownCounter
generic
(
COUNTER_BITS: natural := 4
);
port
(
clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(COUNTER_BITS - 1 downto 0); -- max value counter
counter: out std_logic_vector(COUNTER_BITS - 1 downto 0) -- output 4-bit counter
);
end component;
signal reset, clk, enable, up_down: std_logic;
signal max, counter: std_logic_vector(3 downto 0);
signal halt_clk: boolean := false;
begin
DUT: UpdownCounter
generic map
(
COUNTER_BITS => 4
)
port map
(
clk => clk,
reset => reset,
enable => enable,
up_down => up_down,
max => max,
counter => counter
);
-- Clock
ClockProocess :process
begin
while not halt_clk loop
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end loop;
wait;
end process;
StimulusProcess: process
begin
max <= "1000"; -- Test value for Counter max value
enable <= '1';
reset <= '1';
up_down <= '0';
wait for 20 ns;
reset <= '0';
wait for 300 ns;
up_down <= '1';
--
wait for 50 ns;
enable <= '0';
wait for 50 ns;
enable <= '1';
wait for 1000 ns;
halt_clk <= true;
wait;
end process;
end V1;
Idea is to generate a delayed pulse when Trig input is activated, both delay and pulse width are adjustable respectively with 'delay' and 'ton'. I use an integer counter to compare delay then delay+ton to toggle the Pulse output.
The issue is that timing sequence starts just after board programming: sigPulseCounter is incremented ... even if signals are initialized. Any tips ?
Reset works well and Trig also but there is an unwanted pulse on startup.
Thanks for your feedback.
library ieee;
use ieee.std_logic_1164.all;
entity DelayedMonostable is
generic(
delay :integer:= 2*40000000;
ton :integer:= 2*40000000);
port (
Clk: in std_logic;
Reset: in std_logic;
Trig: in std_logic;
Pulse: out std_logic;
Debug: out std_logic);
end DelayedMonostable;
architecture Behavioral of DelayedMonostable is
-- Signal declaration
signal sigPulseCounterEnable: std_logic := '0';
signal sigPulseCounter : integer := 0;
signal sigPulse : std_logic :='0';
signal sigDebug: std_logic := '0';
begin
Debug <= not sigPulseCounterEnable;
Pulse <= not sigPulse;
Counter : process(Clk, Reset)
begin
if Reset='0' then
sigPulseCounter <= 0;
sigPulseCounterEnable <= '0';
sigPulse <= '0';
elsif Trig='0' then
sigPulseCounter <= 0;
sigPulseCounterEnable <= '1';
sigPulse <= '0';
elsif rising_edge(Clk) then
if(sigPulseCounterEnable='1') then
if(sigPulseCounter = delay) then
sigPulse <= '1';
end if;
if(sigPulseCounter = delay+ton) then
sigPulse <= '0';
sigPulseCounterEnable <= '0';
sigPulseCounter <= 0;
end if;
sigPulseCounter <= sigPulseCounter + 1;
end if;
end if;
end process Counter;
end Behavioral;
I have tried to invert the Trig logic in the process without success:
elsif Trig='0'
with
elsif Trig='1'
EDIT:
I have split in 3 parts the architecture, each assign value to a signal or port - Works good now.
library ieee;
use ieee.std_logic_1164.all;
entity DelayedMonostable is
generic(
delay : integer := 40000000/2;
ton : integer := 2*40000000);
port(
Clk: in std_logic;
Reset: in std_logic;
Trig: in std_logic;
Pulse: out std_logic;
Debug: out std_logic);
end DelayedMonostable;
---------------------------------------
architecture Behavioral of DelayedMonostable is
-- Signal declaration
signal PWMCounter : integer;
signal sigTrig: std_logic;
begin
Debug <= not sigTrig;
Counter : process(Clk, Reset)
begin
if (Reset='0') then
PWMCounter <= 0;
elsif(rising_edge(Clk) and sigTrig='1') then
if(PWMCounter = ton+delay) then
PWMCounter <= 0;
else
PWMCounter <= PWMCounter + 1;
end if;
end if;
end process Counter;
Trigger: process(Reset, Trig)
begin
if (Reset='0') then
sigTrig <= '0';
elsif (Trig='0') then
sigTrig <= '1';
elsif (PwmCounter = ton+delay) then
sigTrig <= '0';
end if;
end process Trigger;
Generator : process(Clk, Reset)
begin
if (Reset='0') then
Pulse <= not '0';
elsif(rising_edge(Clk)) then
if(PwmCounter=delay) then
Pulse <= not '1';
end if;
if(PwmCounter=delay+ton) then
Pulse <= not '0';
end if;
end if;
end process Generator;
end Behavioral;
I'm sending data to and A/D converter and I need the command data to be delayed at least 50ns from clk_19khz. Here is what I have so far.
How do I insert a delay of 50ns which is a requirement for the A/D between the clk_19khz and my first Dout bit to the A/D?
I'm using a Xilinx FPGA. Thanks for the help!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity PSOL is
Port ( clk : in STD_LOGIC;
clk_19khz : OUT std_logic;
Dout :out std_logic);
end PSOL;
architecture Behavioral of PSOL is
signal temp : std_logic;
signal count : integer range 0 to 1301 := 0; --1301
signal temp2 : std_logic;
signal dcount : integer range 0 to 11 := 0; --
signal start : std_logic := '1'; -- indicates the start of
signal parity : std_logic := '1'; --used to varify data sent
signal stop : std_logic := '0'; --indicate when word/command has
--signal chip_select : bit :='1'; -- active low
begin
process (clk)
begin
if (clk' EVENT AND clk='1') then
if (count = 1301) then --1301
temp <= not(temp);
count <=0;
else
count <= count + 1;
end if;
end if;
end process;
clk_19khz <= temp;
temp2 <= temp;
process (temp2)
begin
If (temp2' EVENT and temp2 ='0') then
dcount <= dcount + 1;
parity <= '1';
stop <= '0';
start <='1';
if (dcount < 12 and start = '1' and stop = '0') then
CASE dcount is
when 1 => Dout <= start; -- need delay 50ns before this
when 2 => Dout <= '0';
when 3 => Dout <= '1';
when 4 => Dout <= '0';
when 5 => Dout <= '1';
when 6 => Dout <= '0';
when 7 => Dout <= '0';
when 8 => Dout <= '1';
when 9 => Dout <= '1';
when 10 => Dout <= parity;
when 11 => Dout <= '0';
when others => null;
end case;
end if;
end if;
--dcount <= 0;
--start <='1';
end process;
end Behavioral;
Your clock (50 MHz) has a period of 20 ns. So you'll need a modulo-3 counter to count a delay of at least 3 clock pulses which gives a delay of 60 ns.
Declarations:
signal delay_en : std_logic;
signal delay_us : unsigned(1 downto 0) := (others => '0');
signal delay_ov : std_logic;
Usage:
process(clk)
begin
if rising_edge(clk) then
if (delay_en = '1') then
delay_us <= delay_us + 1;
else
delay_us <= (others => '0');
end if;
end if;
end process;
delay_ov <= '1' when (delay_us = 2) else '0';
Your current implementation needs to drive delay_en while it's waiting for the timespan. If the delay is over, it emits the signal delay_ov (ov = overflow). This can be used by your solution to go on the in algorithm. Your code should also deassert delay_en, what clears the counter to 0.
In the Isim wave window my internal signals and outputs appear green and as initialized but all of my inputs appear as "UU" even though they are initialized as well. I am simply trying to add 1 whenever either of the two inputs are 1. The code synthesizes fine without warnings.
Any ideas?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity scoreboard2 is
Port ( clk : in STD_LOGIC;
T1 : in STD_LOGIC;
T2 : in STD_LOGIC;
Output : out STD_LOGIC_VECTOR (3 downto 0));
end scoreboard2;
architecture Behavioral of scoreboard2 is
signal output_temp: STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal score1,score2: unsigned(1 downto 0) := "00";
signal score3: unsigned(3 downto 0):= "0000";
begin
proc: process(T1,T2,clk)
begin
if(rising_edge(clk)) then
if(T1 = '1') then
score1 <= score1 + 1;
end if;
if(T2 = '1') then
score2 <= score2 + 1;
end if;
end if;
end process proc;
score3 <= score1 & score2;
output_temp <= STD_LOGIC_VECTOR(score3);
Output <= output_temp;
end Behavioral;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY test6 IS
END test6;
ARCHITECTURE behavior OF test6 IS
COMPONENT scoreboard2
PORT(
clk : IN std_logic;
T1 : IN std_logic;
T2 : IN std_logic;
Output : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
--Inputs
signal clk : std_logic := '1';
signal T1 : std_logic := '1';
signal T2 : std_logic := '1';
--Outputs
signal Output : std_logic_vector(3 downto 0) := "0000";
signal output_temp: STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal score1,score2: unsigned(1 downto 0) := "00";
signal score3: unsigned(3 downto 0):= "0000";
constant clk_period : time := 10 ns;
BEGIN
uut: scoreboard2 PORT MAP (
clk => clk,
T1 => T1,
T2 => T2,
Output => Output
);
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stim_proc: process
begin
wait for 100 ns;
T1 <= '1';
wait;
end process;
END;
I don't have Isim but some simulators allow you to run a top level design with a port having unconnected inputs. It's usually synonymous with the ability to do interactive simulation (run, stop, step, force inputs, etc.).
Chapter 5 of ise_tutorial_ug695.pdf, March 1, 2011 (v13.1) says you need a test bench, i don't have all the documentation to determine whether that is enforced or not.
For a test bench:
library ieee;
use ieee.std_logic_1164.all;
entity scoreboard_tb is
end entity;
architecture test of scoreboard_tb is
signal clk: std_logic := '0';
signal T1: std_logic := '0';
signal T2: std_logic := '0';
signal RESULT: std_logic_vector(3 downto 0);
begin
UNDER_TEST:
entity work.scoreboard2
port map (
clk => clk,
T1 => T1,
T2 => T2,
Output => RESULT
);
CLOCK:
process
begin
if Now > 340 ns then -- simulation stops with no signal events
wait;
end if;
clk <= not clk;
wait for 20 ns;
end process;
STIMULUS:
process
begin
wait for 40 ns;
T1 <= '1';
wait for 40 ns;
T2 <= '1';
wait for 40 ns;
T1 <= '0';
T2 <= '0';
wait for 40 ns;
T2 <= '1';
wait for 40 ns;
T2 <= '0';
T1 <= '1';
wait for 40 ns;
T1 <= '0';
wait;
end process;
end architecture;
ghdl produces:
for you're scoreboard2 entity/architecture pair analyzed unchanged.
I don't have Isim either. Probably the softwave itself didn't work well. If there is a wave editor or something similar in Isim, use it instead of a testbench. Then simulate your project again. Hope this helps:)
I am attempting to build a counter in VHDL. Eventual goal is to hook the "do_count" to a button. The total will be converted to BCD and displayed on a 7-segment display. Push the button, watch the numbers increment.
I'm using ModelSim and I can see the internal "counter_value" correctly increment by 1. But the output signal "total" becomes "000X" then "00X0" during my two test "do_count"s. Why am I getting an X'd signal?
I've moved the "output <= current_value" around inside the process, outside the process, inside the 'if's, etc. Still the "000X".
I've tried using a variable 'tmp' inside the process.
count_up : process(clk) is
variable tmp : unsigned (15 downto 0 );
begin
tmp := current_value;
-- snip
if do_count='1' then
current_value <= tmp + to_unsigned(1,16);
end if;
Still I get the "000X".
Full code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity d_counter is
port ( rst : in std_logic;
clk : in std_logic;
do_count : in std_logic;
total : out unsigned (15 downto 0)
);
end entity d_counter;
architecture counter_arch of d_counter is
signal current_value : unsigned (15 downto 0) := (others=>'0');
begin
count_up : process(clk) is
begin
if rst='1' then
current_value <= (others=>'0');
total <= (others=>'0');
elsif rising_edge(clk) then
if do_count='1' then
current_value <= current_value + to_unsigned(1,16);
end if;
end if;
end process count_up;
total <= current_value;
end architecture counter_arch;
Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity test_counter is
begin
end entity test_counter;
architecture run_test_counter of test_counter is
signal t_rst : std_logic := '1';
signal t_clk : std_logic := '0';
signal t_do_count : std_logic;
signal t_total : unsigned( 15 downto 0 );
component d_counter is
port ( rst : in std_logic;
clk : in std_logic;
do_count : in std_logic;
total : out unsigned( 15 downto 0 )
);
end component d_counter;
begin
uut : d_counter
port map( rst => t_rst,
clk => t_clk,
do_count => t_do_count,
total => t_total );
clock : process is
begin
t_clk <= '0'; wait for 10 ns;
t_clk <= '1'; wait for 10 ns;
end process clock;
stimulus : process is
begin
t_rst <= '1';
t_do_count <= '0';
t_total <= (others =>'0');
wait for 15 ns;
t_rst <= '0';
wait for 10 ns;
t_do_count <= '1';
wait for 10 ns;
t_do_count <= '0';
wait for 10 ns;
t_do_count <= '1';
wait for 10 ns;
t_do_count <= '0';
wait for 10 ns;
wait;
end process stimulus;
end architecture run_test_counter;
Update 03-Oct-2012.
BOTH the answers helped. Moving "total <= current_value" inside the process (From #simon) and removing the extra "t_total <= (others =>'0');" (From #peter-bennett) in my testbench was required. I had to do both to get rid of the X's.
It looks like your mistake is in your testbench. The signal t_total is mapped to the total output of your counter component, yet you are writing to it with the t_total <= (others => '0') assignment. If you remove this I think your problem will go away.
uut : d_counter
port map( rst => t_rst,
clk => t_clk,
do_count => t_do_count,
total => t_total );
clock : process is
begin
t_clk <= '0'; wait for 10 ns;
t_clk <= '1'; wait for 10 ns;
end process clock;
stimulus : process is
begin
t_rst <= '1';
t_do_count <= '0';
t_total <= (others =>'0'); <-- Do not assign to t_total (its an output)
Your code write multi-driven with "total". You should delete assigment in process count_up.
count_up : process(clk) is
begin
if rst='1' then
current_value <= (others=>'0');
total <= (others=>'0'); --> Remove it
elsif rising_edge(clk) then
if do_count='1' then
current_value <= current_value + to_unsigned(1,16);
end if;
end if;
end process count_up;
total <= current_value; -- Keep it