有两个立即可见的错误。
第一个计数器没有声明(注释掉,很简单)。
其次,一旦进入 S1 n_state
我想 Brian Drummond 现在会告诉您为您的 FSM 使用一个流程。本质上 input_temp 应该更改为带有存储的东西并移入时钟进程。
您可能会注意到,当 input_temp 变为静态(全为“0”)时,也没有任何东西可以检测。
附录
来自您的评论:
好的,如果我在敏感度列表中添加下一个状态,即 n_state,
它会起作用吗?
没有。如果你看上面的波形,n_state 总是包含 S1。
其次,是的,当它全为 0 时,我什么都看不到,
但是变速部分呢?
最终,一旦达到 input_temp(7),一个“1”就会丢失。
我明确定义了输出
每个州,我应该在这里限制吗?
你可以做三件事。 1. 让输出全部变为“0”,2. 重新循环“1”(约翰逊计数器)或 3. 停止并显示一些 LED。
如果状态是一个热状态,那么新的 8 个状态可以分别驱动一个 LED。 – David Koontz 2 小时前
你:
你能给我举个例子吗?这将有助于我更多地理解
一般来说,这不是教授基本 VHDL 或数字设计技能的正确场所,当然不在评论线程中。它是询问和回答特定 VHDL 问题的场所。见How do I ask a good question?
你问:
请有人告诉我这里出了什么问题。
我回答了,包括一张照片。
就在这里,您可能会注意到上面的波形图像与您问题的第一段冲突:
它根本不移动,只有 LSB 发光,就是这样,我也减慢了时钟,使用 1.5Hz 时钟。
如果您在波形中注意到它恰好移动一次,而您的代码未修改(除了删除您在问题中编辑的未声明的counter 的分配,请参阅下面的第一条评论)。
您定义的是一个两态状态机,要么复位要么移位。它不起作用,因为它没有正确编写。本质上,它描述了当前左移并清空的预期移位寄存器(input_temp)。您的状态是异步复位的触发器,释放时只需切换到另一个状态并假定启用移位。
实现左移(或以相反顺序连接)的 8 位移位寄存器,并且可以通过连接到复位的同步负载(到“00000001”)来实现。 8 个时钟后全是 0。
定义了九种状态(每个 LED 点亮一个状态,一个所有 LED 熄灭的状态)您可以通过添加该状态触发器来添加第 10 个状态。您可以使用 10 个触发器来实现一个热状态机,8 个触发器仅用于移位寄存器或 9 个触发器包含 c_state(和复位保持)。
我可以假设为上述两段生成三种不同的架构,但我不打算这样做。
这是对代码更改最少的最简单的实现:
architecture foo of scan is
type state is ( RESET_ST, S1 );
signal n_state: state;
signal c_state: state;
-- signal input_temp: unsigned (7 downto 0):= "00000001";
signal shft_reg: std_logic_vector (7 downto 1);
begin
state_assignment:
process (clk, reset)
begin
if reset = '1' then
c_state <= RESET_ST;
-- counter <= (others => '0');
shft_reg <= (others => '0');
elsif clk'event and clk = '1' then
c_state <= n_state;
if c_state = RESET_ST then
shft_reg <= shft_reg (6 downto 1) & '1';
elsif shft_reg /= "1000000" then
shft_reg <= shft_reg (6 downto 1) & '0';
end if;
end if;
end process;
--input_block :
NEXT_STATE:
process (c_state)
begin
case (c_state) is
when RESET_ST =>
-- input_temp <= "00000001";
n_state <= S1;
when S1 =>
-- input_temp <= input_temp (6 downto 0) & '0';
n_state <= S1;
when others =>
n_state <= RESET_ST;
end case;
end process;
-- output_block:
-- process (c_state, input_temp)
-- begin
-- case (c_state) is
-- when RESET_ST =>
-- led <= std_logic_vector (input_temp);
-- when S1 =>
-- led <= std_logic_vector (input_temp);
-- when others =>
-- led <= (others => '1');
-- end case;
-- end process;
-- LED0_OUT:
-- led(0) <= '1' when c_state = RESET_ST else '0';
LEDOUT:
process (c_state, shft_reg)
begin
if c_state = RESET_ST then
led(0) <= '1';
else
led(0) <= '0';
end if;
led (7 downto 1) <= shft_reg; -- shft_reg(7 downto 1)
end process;
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity scan_tb is
end entity;
architecture foo of scan_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '1';
signal led: std_logic_vector ( 7 downto 0);
begin
DUT:
entity work.scan
port map (
clk => clk,
led => led,
reset => reset
);
CLOCK:
process
begin
wait for 0.33 sec; -- one half clock period, 1.5 Hz
clk <= not clk;
if Now > 20 sec then
wait;
end if;
end process;
STIMULUS:
process
begin
wait until rising_edge(clk);
wait for 0.33 sec;
wait until rising_edge(clk);
reset <= '0';
wait;
end process;
end architecture;
波形如下:
请注意,波形中 LED 的基数已更改为二进制。
还要注意两个波形的第一部分匹配。我还添加了一个 shft_reg 状态识别器以在设置 led(7) 时冻结 shft_reg。
您还可以注意到有一个优化。第一个 LED 被驱动关闭 c_state,其余 7 个被驱动关闭 7 位移位寄存器 (shft_reg)。还要注意的是,只使用了 8 个触发器。
正如 sonicwave 在对您的问题的评论中指出的那样,您应该首先真正模拟这些东西,所以这里有一个简单的测试台。
这是模拟的,使用删除了包 numeric_std 的 use 子句的实体声明(shft_reg 是 std_logic_vector 类型)、新架构 foo 和使用 ghdl-0.31 的 scan_tb 的实体/架构对:
david_koontz@Macbook: ghdl -a scan.vhdl
david_koontz@Macbook: ghdl -e scan_tb
david_koontz@Macbook: ghdl -r scan_tb --wave=scan_tb.ghw
在运行 OS X 10.9.3 的 Mac 上,其中 scan_tb.ghw 是 ghdl 特定的波形转储文件格式,非常适合 VHDL。
现在,请不要再在 cmets 上向您最初提出的问题添加更多问题。您也可以在示例代码中注释掉对未声明信号计数器的分配,而不是对其进行编辑。它破坏了问题和答案之间的连续性。
进一步
状态分配过程可以在不评估c_state的情况下编写:
state_assignment:
process (clk, reset)
begin
if reset = '1' then
c_state <= RESET_ST;
-- counter <= (others => '0');
shft_reg <= (others => '0');
elsif clk'event and clk = '1' then
c_state <= n_state;
-- if c_state = RESET_ST then
if shft_reg = "0000000" then
shft_reg <= shft_reg (6 downto 1) & '1';
elsif shft_reg /= "1000000" then
shft_reg <= shft_reg (6 downto 1) & '0';
end if;
end if;
end process;
它做同样的事情。
现在多评论一下:
state_assignment:
process (clk, reset)
begin
if reset = '1' then
c_state <= RESET_ST;
-- counter <= (others => '0');
shft_reg <= (others => '0');
elsif clk'event and clk = '1' then
c_state <= n_state;
-- if c_state = RESET_ST then
if shft_reg = "0000000" then
shft_reg <= shft_reg (6 downto 1) & '1';
-- elsif shft_reg /= "1000000" then
else
shft_reg <= shft_reg (6 downto 1) & '0';
end if;
end if;
end process;
并在 LEDOUT 过程中做出同样的决定改变:
LEDOUT:
process (shft_reg)
begin
if shft_reg = "0000000" then
led(0) <= '1';
else
led(0) <= '0';
end if;
led (7 downto 1) <= shft_reg; -- shft_reg(7 downto 1)
end process;
您可以让扫描 LED 继续扫描:
我们已将 LED(0) 切换为不依赖其他 shft_reg 位置设置为“1”(不是“0”)。