【发布时间】:2021-12-29 06:52:17
【问题描述】:
我想知道是否有人可以给我一些建议。我正在尝试设计一个需要 8 个输入(按钮)的模块。 这些按钮确定状态是否处于活动状态。然后在时钟的上升沿,它通过活动状态依次向前或向后移动, 跳过非活动时钟状态。
例如:
如果输入为 11111111,则连续计数 00000001、00000010、00000100、00001000、00010000、00100000、01000000、10000000。
如果输入为 00001111。它会连续计数 00000001、00000010、00000100、00001000。
如果输入是 00000011。它会连续计数 00000001, 00000010。
我是 VHDL 和 fpga 的新手。我尝试了几种不同的方法。他们都有过 问题。但是我写的这个状态机正在按照我想要的方式工作。 它基本上从状态 0 开始,检查它的移动方向,然后检查该方向中的下一个活动状态并移动到它。
例如:
如果处于状态 0 并向前移动,则检查输入 2,如果向后移动,则检查输入 8。如果它们未处于活动状态,则检查输入 3 和输入 7。 如果它们处于活动状态,它会移动到该状态并再次执行该过程。但是这次因为我们处于不同的状态,它从这个新状态开始检查。如果我们处于状态 2。如果向前则检查输入 3,如果向后则检查输入 1。如果处于活动状态,它会移动到该状态。
它有点长,有很多重复的代码,很像 C 代码。如果可以的话,我想摆脱这种情况。但正如我所说,我的知识有限,我想知道是否有更好的方法来实现我需要的功能。任何帮助和指导将不胜感激,我提前感谢您。
这是模块的代码。
library ieee;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
ENTITY state_machine IS
PORT(
clk : IN STD_LOGIC;
a : IN STD_LOGIC; -- state0 Active '1'
b : IN STD_LOGIC; -- state1 Active '1'
c : IN STD_LOGIC; -- state2 Active '1'
d : IN STD_LOGIC; -- state3 Active '1'
e : IN STD_LOGIC; -- state4 Active '1'
f : IN STD_LOGIC; -- state5 Active '1'
g : IN STD_LOGIC; -- state6 Active '1'
h : IN STD_LOGIC; -- state7 Active '1'
dir : IN STD_LOGIC; -- direction
reset : IN STD_LOGIC;
output : OUT STD_LOGIC_VECTOR(2 downto 0));
END state_machine;
ARCHITECTURE behaviour OF state_machine IS
TYPE STATE_TYPE IS (s0, s1, s2, s3, s4, s5, s6, s7);
SIGNAL state : STATE_TYPE;
BEGIN
sequence: PROCESS (clk, reset)
BEGIN
IF reset = '1' THEN
state <= s0;
ELSIF (rising_edge (clk)) THEN
CASE state IS
WHEN s0=> -- When in state 0
IF (dir = '1') THEN -- if direction is forwards
IF b = '1' THEN state <= s1; -- If b is 1 go to state 1...if not
elsif c = '1' then state <= s2; -- if c is 1 go to state 2...if not
elsif d = '1' then state <= s3; -- if d is 1 go to state 3...if not
elsif e = '1' then state <= s4; -- if e is 1 go to state 4...if not
elsif f = '1' then state <= s5; -- if f is 1 go to state 5...if not
elsif g = '1' then state <= s6; -- if g is 1 go to state 6...if not
elsif h = '1' then state <= s7; -- if h is 1 go to state 7...if not
elsif a = '1' then state <= s0; -- if a is 1 go to state 0
END IF;
ELSE -- if direction is backwards
IF h = '1' THEN state <= s7; -- If h is 1 go to state 1...if not
elsif g = '1' then state <= s6; -- if g is 1 go to state 2...if not
elsif f = '1' then state <= s5; -- if f is 1 go to state 3...if not
elsif e = '1' then state <= s4; -- if e is 1 go to state 4...if not
elsif d = '1' then state <= s3; -- if d is 1 go to state 5...if not
elsif c = '1' then state <= s2; -- if c is 1 go to state 6...if not
elsif b = '1' then state <= s1; -- if b is 1 go to state 7...if not
elsif a = '1' then state <= s0; -- if a is 1 go to state 0...if not
END IF;
END IF;
WHEN s1=>
IF (dir = '1') THEN
IF c = '1' THEN state <= s2;
elsif d = '1' then state <= s3;
elsif e = '1' then state <= s4;
elsif f = '1' then state <= s5;
elsif g = '1' then state <= s6;
elsif h = '1' then state <= s7;
elsif a = '1' then state <= s0;
elsif b = '1' THEN state <= s1;
END IF;
ELSE
IF a = '1' THEN state <= s0;
elsif h = '1' then state <= s7;
elsif g = '1' then state <= s6;
elsif f = '1' then state <= s5;
elsif e = '1' then state <= s4;
elsif d = '1' then state <= s3;
elsif c = '1' then state <= s2;
elsif b = '1' then state <= s1;
END IF;
END IF;
WHEN s2=>
IF (dir = '1') THEN
IF d = '1' THEN state <= s3;
elsif e = '1' then state <= s4;
elsif f = '1' then state <= s5;
elsif g = '1' then state <= s6;
elsif h = '1' then state <= s7;
elsif a = '1' then state <= s0;
elsif b = '1' then state <= s1;
elsif c = '1' then state <= s2;
END IF;
ELSE
IF b = '1' THEN state <= s1;
elsif a = '1' then state <= s0;
elsif h = '1' then state <= s7;
elsif g = '1' then state <= s6;
elsif f = '1' then state <= s5;
elsif e = '1' then state <= s4;
elsif d = '1' then state <= s3;
elsif c = '1' then state <= s2;
END IF;
END IF;
WHEN s3=>
IF (dir = '1') THEN
IF e = '1' THEN state <= s4;
elsif f = '1' then state <= s5;
elsif g = '1' then state <= s6;
elsif h = '1' then state <= s7;
elsif a = '1' then state <= s0;
elsif b = '1' then state <= s1;
elsif c = '1' then state <= s2;
elsif d = '1' then state <= s3;
END IF;
ELSE
IF c = '1' THEN state <= s2;
elsif b = '1' then state <= s1;
elsif a = '1' then state <= s0;
elsif h = '1' then state <= s7;
elsif g = '1' then state <= s6;
elsif f = '1' then state <= s5;
elsif e = '1' then state <= s4;
elsif d = '1' then state <= s3;
END IF;
END IF;
WHEN s4=>
IF (dir = '1') THEN
IF f = '1' THEN state <= s5;
elsif g = '1' then state <= s6;
elsif h = '1' then state <= s7;
elsif a = '1' then state <= s0;
elsif b = '1' then state <= s1;
elsif c = '1' then state <= s2;
elsif d = '1' then state <= s3;
elsif e = '1' then state <= s4;
END IF;
ELSE
IF d = '1' THEN state <= s3;
elsif c = '1' then state <= s2;
elsif b = '1' then state <= s1;
elsif a = '1' then state <= s0;
elsif h = '1' then state <= s7;
elsif g = '1' then state <= s6;
elsif f = '1' then state <= s5;
elsif e = '1' then state <= s4;
END IF;
END IF;
WHEN s5=>
IF (dir = '1') THEN
IF g = '1' THEN state <= s6;
elsif h = '1' then state <= s7;
elsif a = '1' then state <= s0;
elsif b = '1' then state <= s1;
elsif c = '1' then state <= s2;
elsif d = '1' then state <= s3;
elsif e = '1' then state <= s4;
elsif e = '1' then state <= s5;
END IF;
ELSE
IF e = '1' THEN state <= s4;
elsif d = '1' then state <= s3;
elsif c = '1' then state <= s2;
elsif b = '1' then state <= s1;
elsif a = '1' then state <= s0;
elsif h = '1' then state <= s7;
elsif g = '1' then state <= s6;
elsif f = '1' then state <= s5;
END IF;
END IF;
WHEN s6=>
IF (dir = '1') THEN
IF h = '1' THEN state <= s7;
elsif a = '1' then state <= s0;
elsif b = '1' then state <= s1;
elsif c = '1' then state <= s2;
elsif d = '1' then state <= s3;
elsif e = '1' then state <= s4;
elsif f = '1' then state <= s5;
elsif g = '1' then state <= s6;
END IF;
ELSE
IF f = '1' THEN state <= s5;
elsif e = '1' then state <= s4;
elsif d = '1' then state <= s3;
elsif c = '1' then state <= s2;
elsif b = '1' then state <= s1;
elsif a = '1' then state <= s0;
elsif h = '1' then state <= s7;
elsif g = '1' then state <= s6;
END IF;
END IF;
WHEN s7=>
IF (dir = '1') THEN
IF a = '1' THEN state <= s0;
elsif b = '1' then state <= s1;
elsif c = '1' then state <= s2;
elsif d = '1' then state <= s3;
elsif e = '1' then state <= s4;
elsif f = '1' then state <= s5;
elsif g = '1' then state <= s6;
elsif h = '1' then state <= s7;
END IF;
ELSE
IF g = '1' THEN state <= s6;
elsif f = '1' then state <= s5;
elsif e = '1' then state <= s4;
elsif d = '1' then state <= s3;
elsif c = '1' then state <= s2;
elsif b = '1' then state <= s1;
elsif a = '1' then state <= s0;
elsif h = '1' then state <= s7;
END IF;
END IF;
END CASE;
END IF;
END PROCESS;
PROCESS (state)
BEGIN
CASE state IS
WHEN s0 =>
output <= "000";
WHEN s1 =>
output <= "001";
WHEN s2 =>
output <= "010";
WHEN s3 =>
output <= "011";
WHEN s4 =>
output <= "100";
WHEN s5 =>
output <= "101";
WHEN s6 =>
output <= "110";
WHEN s7 =>
output <= "111";
END CASE;
END PROCESS;
END behaviour;
这里是测试台:
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;
entity state_machine_tb is
end;
architecture bench of state_machine_tb is
component state_machine
PORT(
clk : IN STD_LOGIC;
a : IN STD_LOGIC;
b : IN STD_LOGIC;
c : IN STD_LOGIC;
d : IN STD_LOGIC;
e : IN STD_LOGIC;
f : IN STD_LOGIC;
g : IN STD_LOGIC;
h : IN STD_LOGIC;
dir : IN STD_LOGIC;
reset : IN STD_LOGIC;
output : OUT STD_LOGIC_VECTOR(2 downto 0));
end component;
signal clk : STD_LOGIC;
signal a : STD_LOGIC;
signal b : STD_LOGIC;
signal c : STD_LOGIC;
signal d : STD_LOGIC;
signal e : STD_LOGIC;
signal f : STD_LOGIC;
signal g : STD_LOGIC;
signal h : STD_LOGIC;
signal dir : STD_LOGIC;
signal reset : STD_LOGIC;
signal output : STD_LOGIC_VECTOR(2 downto 0);
constant clock_period: time := 10 ns;
begin
uut: state_machine port map ( clk => clk,
a => a,
b => b,
c => c,
d => d,
e => e,
f => f,
g => g,
h => h,
dir => dir,
reset => reset,
output => output);
stimulus: process
begin
reset <= '1';
dir <= '1';
a <= '1';
b <= '1';
c <= '1';
d <= '1';
e <= '1';
f <= '1';
g <= '1';
h <= '1';
wait for clock_period;
reset <= '0';
wait for clock_period *15;
dir <= '0';
a <= '1';
b <= '1';
c <= '1';
d <= '1';
e <= '1';
f <= '1';
g <= '1';
h <= '1';
wait for clock_period *16;
dir <= '1';
a <= '1';
b <= '1';
c <= '1';
d <= '1';
e <= '0';
f <= '0';
g <= '0';
h <= '0';
wait for clock_period *16;
dir <= '0';
a <= '1';
b <= '1';
c <= '1';
d <= '1';
e <= '0';
f <= '0';
g <= '0';
h <= '0';
wait for clock_period *16;
dir <= '1';
a <= '1';
b <= '0';
c <= '1';
d <= '0';
e <= '1';
f <= '0';
g <= '1';
h <= '0';
wait for clock_period *16;
a <= '1';
b <= '1';
c <= '0';
d <= '0';
e <= '0';
f <= '0';
g <= '0';
h <= '0';
wait for clock_period *16;
a <= '1';
b <= '0';
c <= '0';
d <= '0';
e <= '0';
f <= '0';
g <= '0';
h <= '0';
wait for clock_period *4;
dir <= '0';
wait;
end process;
clocking: process
begin
clk <= '0';
wait for clock_period / 2;
clk <= '1';
wait for clock_period / 2;
end process;
end;
【问题讨论】:
-
从细化规范开始。我们知道“00001111”是做什么的,但是“00001000”呢?还是“00001110”?然后寻找一些可以用来简化问题描述的规律性。正如 Renaud 所建议的,你有一个类型系统;使用它和计数等会容易得多。
标签: if-statement vhdl counter state-machine