Существует множество способов описания счетчиков в VHDL.
Если вы хотите реализовать счетчик структурным способом, ваш реализованный метод является текущим способом, но будет лучше, если вы будете использовать векторы вместо простых сигналов. Это делает код очень четким и читабельным.
- в вашем модуле ddf можно удалить одно из операторов IF
- в счетчике вы не хотите использовать q в режиме ввода, так что лучший способ для использования, это определить внутренние сигналы и присвоить то q
Например, вы можете сильфонный стиль:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY dff IS
PORT
(
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
din : IN STD_LOGIC;
qout : OUT STD_LOGIC
);
END dff;
ARCHITECTURE behavioral OF dff IS
BEGIN
PROCESS (clk, rst)
BEGIN
IF (rst = '0') THEN
qout<='0';
ELSIF(clk = '1' AND clk'EVENT) THEN
qout <= din;
END IF;
END PROCESS;
END behavioral;
и для описания стиля счетчика ниже:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY upcount4 IS
PORT
(
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
en : IN STD_LOGIC;
qout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END upcount4;
ARCHITECTURE rt_level OF upcount4 IS
COMPONENT dff IS
PORT
(
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
din : IN STD_LOGIC;
qout : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL dffs_out : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL dffs_in : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL ands_out : STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
ands_out(0) <= en AND dffs_out(0);
ands_out(1) <= ands_out(0) AND dffs_out(1);
ands_out(2) <= ands_out(1) AND dffs_out(2);
dffs_in(0) <= en XOR dffs_out(0);
dffs_in(1) <= ands_out(0) XOR dffs_out(1);
dffs_in(2) <= ands_out(1) XOR dffs_out(2);
dffs_in(3) <= ands_out(2) XOR dffs_out(3);
qout <= dffs_out;
dff_0:dff
PORT MAP
(
clk => clk,
rst => rst,
din => dffs_in(0),
qout => dffs_out(0)
);
dff_1:dff
PORT MAP
(
clk => clk,
rst => rst,
din => dffs_in(1),
qout=> dffs_out(1)
);
dff_2:dff
PORT MAP
(
clk => clk,
rst => rst,
din => dffs_in(2),
qout=> dffs_out(2)
);
dff_3:dff
PORT MAP
(
clk => clk,
rst => rst,
din => dffs_in(3),
qout=> dffs_out(3)
);
END rt_level;
Когда экземпляры модулей имеют одинаковые параметры, мы можем использовать красивое выражение под названием FOR GENERATE
. Вы можете использовать стиль ниже:
ARCHITECTURE rt_levelgen OF upcount4 IS
COMPONENT dff IS
PORT
(
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
din : IN STD_LOGIC;
qout : OUT STD_LOGIC
);
END COMPONENT;
SIGNAL dffs_out : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL dffs_in : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL ands_out : STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
ands_out(0) <= en AND dffs_out(0);
ands_out(1) <= ands_out(0) AND dffs_out(1);
ands_out(2) <= ands_out(1) AND dffs_out(2);
dffs_in(0) <= en XOR dffs_out(0);
dffs_in(1) <= ands_out(0) XOR dffs_out(1);
dffs_in(2) <= ands_out(1) XOR dffs_out(2);
dffs_in(3) <= ands_out(2) XOR dffs_out(3);
qout <= dffs_out;
generate_label:
FOR index in 0 to 3 GENERATE
dffs_0_3_label:dff
PORT MAP
(
clk => clk,
rst => rst,
din => dffs_in(index),
qout => dffs_out(index)
);
END GENERATE;
END rt_levelgen;
Если вы не хотите реализовывать счетчик со структурной моделью, вы можете описать его в поведенческой модели, и инструмент реализации (например, Vivado или ISE) преобразует его в реальное оборудование (например, зарегистрируетесь с сумматором).
Ниже приведен код описания поведения в поведенческой модели:
ARCHITECTURE behavioral OF upcount4 IS
SIGNAL counter : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(reset,clock)
BEGIN
IF(reset = '0') THEN
counter <= (OTHERS => '0');
ELSIF( RISING_EDGE(clock) )THEN
IF(enable = '1') THEN
counter <= counter + X"1";
END IF;
END IF;
END PROCESS;
qout <= counter;
END behavioral;
Модуль испытательного стенда и форма волны
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY counter_tb IS
END counter_tb;
ARCHITECTURE behavior OF counter_tb IS
COMPONENT upcount4
PORT(
clk : IN std_logic;
rst : IN std_logic;
en : IN std_logic;
qout : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal en : std_logic := '0';
signal qout : std_logic_vector(3 downto 0);
BEGIN
uut: upcount4 PORT MAP(
clk => clk,
rst => rst,
en => en,
qout => qout);
clk <= NOT clk AFTER 5 NS;
rst <= '0',
'1' AFTER 30 NS;
en <= '0',
'1' AFTER 40 NS,
'0' AFTER 70 NS,
'1' AFTER 90 NS;
END;
![Simulation Waveform](https://cdn.pbrd.co/images/HOckLyZ.png)
Хороший замок!