我正在尝试运行一个扫描LED的简单FSM。我通过将位移到左边,使用了&来应用这个逻辑。操作员。它完全没有移动LSB发光,也就是说,我也使用1.5Hz时钟减慢时钟速度。有人请告诉我这里有什么问题。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity scan is
Port (
clk : in STD_LOGIC;
led : out STD_LOGIC_VECTOR (7 downto 0);
reset : in STD_LOGIC
);
end scan;
architecture Behavioral 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";
begin
--------------------------------------------------------------------------
--------------------------CURRENT STATE ASSIGNMENT------------------------
--------------------------------------------------------------------------
STATE_ASSIGNMENT: process (clk, reset)
begin
if (reset = '1') then
c_state <= RESET_ST;
elsif (clk'event and clk = '1') then
c_state <= n_state;
end if;
end process STATE_ASSIGNMENT;
--------------------------------------------------------------------------
----------------------------- INTPUT BLOCK--------------------------------
--------------------------------------------------------------------------
INPUT_BLOCK : 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--------------------------------
--------------------------------------------------------------------------
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 OUTPUT_BLOCK;
end Behavioral;
答案 0 :(得分:1)
有两个立即可见的错误。
未宣布第一个计数器(注释掉,很容易)。
第二,一旦进入S1 n_state&lt; = S1,换句话说,你去S1并坐在那里。这样做的结果是INPUT_BLOCK进程没有触发事件 - 灵敏度只包含c_state而且c_state没有进一步的变化。
我想想Brian Drummond现在会告诉你现在为你的FSM使用一个过程。基本上input_temp应该更改为带存储的东西并移入时钟进程。
您可以注意到,当input_temp变为静态(所有&#39; 0&#39; s)时,无法检测到任何内容。
<强>附录强>
来自你的评论:
好的,如果我在灵敏度列表中添加下一个状态,即n_state, 它会起作用吗?
没有。如果你查看上面的波形,n_state总是包含S1。
其次是的,当它全部发生时,我什么也看不见, 但转变部分呢?
最终那个&#39; 1&#39;一旦达到input_temp(7)就会迷路。
我明确定义了输出 每个州,我应该在这里设置限制吗?
你可以做三件事。 1.让输出全部转到&#39; 0,2。再循环&#39; 1&#39; (约翰逊柜台)或3.停下来显示一些LED。
如果状态很热,新的8个州可以分别驱动LED。 - David Koontz 2小时前
你:
你能不能给我一个例子或什么?这将有助于我更多地理解
一般来说,这不是教授基本VHDL或数字设计技能的正确场所,当然不是在评论主题中。它是询问和回答特定VHDL问题的场所。见How do I ask a good question?
你问:
有人请告诉我这里有什么问题。
我回答,包括一张照片。
就在这里你可以注意到上面的波形图与你问题的第一段相冲突:
它完全没有移动只有LSB发光,就是这样,我也使用1.5Hz时钟减慢时钟速度。
如果你在波形中注意它只改变了一次,你的代码没有修改(除了删除你编辑过的未申报counter
的作业,请参阅下面的第一条评论)。
您定义的是两个状态机重置或移位。它不起作用,因为它没有正确编写。它必不可少地描述了当前向左移位和清空的预期移位寄存器(input_temp)。你的状态是一个触发器运行异步复位,当释放时只是切换到另一个状态,并据说启用了移位。
实现向左移位(或以相反顺序连接)的8位移位寄存器,并且可以通过连接到复位的同步加载(到&#34; 00000001&#34;)来实现。 8个时钟之后它全部都是
。定义了九个状态(每个LED点亮一个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是一种非常适合VHDL的ghdl特定波形转储文件格式。
现在,请不要再对您最初提出的问题的评论中提出更多问题。此外,您可以在示例代码中注释掉未声明信号计数器的分配,而不是将其编辑出来。它破坏了问题和答案之间的连续性。
<强>进一步强>
可以在不评估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位置被设置为&#39; 1&#39; (不是&#39; 0&#39;)。