问题
I'm trying to make a 32 bit counter in VHDL. Below is my code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY counter32 IS
PORT (en, clk, clr: IN STD_LOGIC;
count: OUT STD_LOGIC_VECTOR(4 DOWNTO 0));
END counter32;
ARCHITECTURE rtl OF counter32 IS
SIGNAL count_result: STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
counter32: PROCESS(clk, clr)
BEGIN
count <= "00000"; --Initialize counter to all zeroes
IF (clr = '0') THEN
count_result <= "00000";
ELSIF (clk = '1' and clk'EVENT) THEN
IF (en = '1') THEN
count <= STD_LOGIC_VECTOR(unsigned(count_result) + 1);
count <= STD_LOGIC_VECTOR(count_result);
ELSIF (count_result = "11111") THEN
count_result <= "00000";
END IF;
END IF;
END PROCESS counter32;
END rtl;
My test bench code is here:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter32_tb is
end counter32_tb;
architecture io of counter32_tb is
component counter32 is
port(en,clk,clr:in std_logic; count:out std_logic_vector(4 downto 0));
end component;
for all: counter32 use entity work.counter32(rtl);
signal en,clk,clr:std_logic;
signal count:std_logic_vector(4 downto 0);
begin
count <= "00000";
g0: counter32 port map(en,clk,clr,count);
p0: process
begin
en <= '1';
clk <= '0';
clr <= '1';
wait for 10ns;
en <= '1';
clk <= '1';
clr <= '1';
wait for 10ns;
en <= '1';
clk <= '0';
clr <= '1';
wait for 10ns;
en <= '1';
clk <= '1';
clr <= '1';
wait for 10ns;
en <= '1';
clk <= '0';
clr <= '1';
wait for 10ns;
en <= '1';
clk <= '1';
clr <= '0';
end process;
end io;
Whenever I test, however, an addition of 1 gives a 'U' STD_LOGIC value and a red bar in testing, as you can see here:
Any idea what the matter is? I'm really confused!
回答1:
Any idea what the matter is?
Your waveform doesn't match your test bench stimulus.
There are three assignments to the signal count which appears to show in your waveform (at the test bench level). An initial assignment to "00000", and two conditional assignments. The bouncing back and forth is caused by the process sensitity to clk, bouncing back to "00000" on the following edge of clock using the first assignment statement.
In a process statement the last assignment is the one that takes effect. You're writing it to "00000" and changing that to count_result conditionally based on the positive edge of clock. Note that you aren't actually loading count with count_result + 1 either, the next assignment provides the current value of count_result. While we're on the subject the type conversion to std_logic_vector isn't needed either, count_result is already a std_logic_vector.
The unknown (red) 'flash' at the clock edge is because you haven't actually cleared count_result. The only event on clr is from 'U' to '1' and causes no clear.
The vhdl design code is not functional as a counter.
This:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter32 is
port (
en, clk, clr: in std_logic;
count: out std_logic_vector(4 downto 0)
);
end counter32;
architecture rtl of counter32 is
signal count_result: std_logic_vector(4 downto 0);
begin
counter: process(clk, clr)
begin
if clr = '0' then
count_result <= (others => '0');
elsif clk = '1' and clk'event and en = '1' then
count_result <= std_logic_vector(unsigned(count_result) + 1);
end if;
end process;
count <= count_result;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
entity counter32_tb is
end entity;
architecture foo of counter32_tb is
signal en: std_logic:= '0';
signal clr: std_logic:= '1';
signal clk: std_logic:= '0';
signal count: std_logic_vector (4 downto 0);
begin
DUT: entity work.counter32
port map (
en => en,
clk => clk,
clr => clr,
count => count
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 720 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
clr <= '0';
en <= '1';
wait for 20 ns;
clr <= '1';
wait for 20 ns;
wait for 20 ns;
wait for 20 ns;
wait for 20 ns;
wait for 20 ns;
en <= '0';
wait for 20 ns;
en <= '1';
wait;
end process;
end architecture;
Gives this:
The reason no end cases are necessary in the count arithmetic are due to how the unsigned "+" operator works, calling unsigned_add in the package body for numeric_std. End counts are something you need to worry about in scalar increments.
The purpose behind having count (mode out) and count_result, is to allow the count value to be read internally for versions of VHDL predating IEEE Std 1076-2008. For a -2008 compliant simulation you should be only using count. Note the above simulation shown will run on earlier versions of VHDL.
You could likewise make count_result a variable.
And I trust you're aware based on signal array sizes this is a 5 bit counter and not a 32 bit counter. Converting to the latter is relatively easy.
来源:https://stackoverflow.com/questions/22367459/counter-not-testing-as-expected-vhdl