我被要求使用单热编码创建一个有限状态机,该编码将检测输入w上的四个1或0的序列。我已经使用case语句编写了代码,但我还必须通过提供逻辑表达式作为9个触发器的输入来实现。我没有在z上获得正确的输出,我无法弄清楚原因。
到目前为止,我为D触发器编写了以下代码
library ieee;
use ieee.std_logic_1164.all;
entity dflipflop is
port (D, clk, reset: in std_logic;
Q: out std_logic);
end dflipflop;
architecture behavior of dflipflop is
begin
process(clk)
begin
if reset <= '0' then
Q <= '0';
elsif rising_edge(clk) then
Q <= D;
end if;
end process;
end behavior;
然后我将此作为我的其余代码,这是我认为问题所在。
library ieee;
use ieee.std_logic_1164.all;
entity part1 is
port (clk, w, reset : in std_logic;
z: out std_logic);
end part1;
architecture behavior of part1 is
component dflipflop
port (D, clk, reset: in std_logic;
Q: out std_logic);
end component;
signal A, B, C, D, E, F, G, H, I: std_logic;
signal Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8, Y9: std_logic;
dff1: dflipflop port map (clk=>clk, reset=>reset, D=>Y1, Q=>A);
dff2: dflipflop port map (clk=>clk, reset=>reset, D=>Y2, Q=>B);
dff3: dflipflop port map (clk=>clk, reset=>reset, D=>Y3, Q=>C);
dff4: dflipflop port map (clk=>clk, reset=>reset, D=>Y4, Q=>D);
dff5: dflipflop port map (clk=>clk, reset=>reset, D=>Y5, Q=>E);
dff6: dflipflop port map (clk=>clk, reset=>reset, D=>Y6, Q=>F);
dff7: dflipflop port map (clk=>clk, reset=>reset, D=>Y7, Q=>G);
dff8: dflipflop port map (clk=>clk, reset=>reset, D=>Y8, Q=>H);
dff9: dflipflop port map (clk=>clk, reset=>reset, D=>Y9, Q=>I);
begin
process(clk);
begin
if rising_edge(clk) then
Y1 <= (((not w) and C) or ((not w) and G) or ((not w) and H) or ((not w) and I) or (w and B) or (w and D) or (w and E) or (w and F));
Y2 <= ((not w) and A);
Y3 <= (w and A);
Y4 <= ((not w) and B);
Y5 <= ((not w) and D);
Y6 <= (((not w) and E) or ((not w) and F));
Y7 <= (w and C);
Y8 <= (w and G);
Y9 <= ((w and H) or (w and I));
end if;
end process;
z <= (Y6 OR Y9);
end behavior;
任何人都可以提供任何有关我可能做错的提示或见解吗?
答案 0 :(得分:1)
您的 dflipflop 描述似乎很好,但我没有看到使用异步重置的任何原因。考虑将其更改为synchronous reset flip-flop,除非您的设计需要一些FF来异步重置。
您已将组合逻辑句子放入时钟进程中。现在,如果你要在结构上实例化触发器,那么所有这些句子都不应该在其中,因为它们已经被触发器计时。
您应该更明智地使用信号名称,否则您的代码将非常难以阅读和调试,尤其是对于更复杂的设计。另外,如果您想分别进行高电平有效或低电平有效复位,请使用reset= '1'
或reset='0'
代替reset <='0'
。
我相信您正在寻找具有以下图形表示的位检测器的简单有限状态机(FSM)的结构描述,以及总共9个状态。单热编码意味着您需要为每个状态分配一个触发器。
首先,声明9个std_logic信号,其中每个信号代表一个状态 一个热门的FSM。这些将是9的输出信号 的FF:
signal init : std_logic; -- Initial/reset state
signal zeros_1 : std_logic; -- 1 zero detected
signal zeros_2 : std_logic; -- 2 zeros detected
signal zeros_3 : std_logic; -- 3 zeros detected
signal zeros_4 : std_logic; -- 4 zeros detected
signal ones_1 : std_logic; -- 1 one detected
signal ones_2 : std_logic; -- 1 one detected
signal ones_3 : std_logic; -- 1 one detected
signal ones_4 : std_logic; -- 1 one detected
声明额外的9个std_logic信号,以保存下一个值 相应的状态Flip Flop。这些将是输入信号 9个FF:
signal go_to_init : std_logic;
signal go_to_zeros_1 : std_logic;
signal go_to_zeros_2 : std_logic;
signal go_to_zeros_3 : std_logic;
signal go_to_zeros_4 : std_logic;
signal go_to_ones_1 : std_logic;
signal go_to_ones_2 : std_logic;
signal go_to_ones_3 : std_logic;
signal go_to_ones_4 : std_logic;
将9个触发器映射到相应的信号。
注意,如果你想用RESET信号初始化状态机,你需要一个D触发器,它在RESET时为高电平。您可以使用 dflipflop 的说明,将if reset='1' then Q <='0'
更改为if reset='1' then Q <='1'
并使用它来实施新的 dflipflop_RH 。
init_ff : dflipflop_RH port map (clk=>clk, reset=>reset,D=> go_to_init, Q=> init);
zeros_1_ff: dflipflop port map (clk=>clk, reset=>reset,D=> go_to_zeros_1, Q=> zeros_1 );
zeros_2_ff: dflipflop port map (clk=>clk, reset=>reset,D=> go_to_zeros_2, Q=> zeros_2 );
zeros_3_ff: dflipflop port map (clk=>clk, reset=>reset,D=> go_to_zeros_3, Q=> zeros_3 );
zeros_4_ff: dflipflop port map (clk=>clk, reset=>reset,D=> go_to_zeros_4, Q=> zeros_4 );
ones_1_ff : dflipflop port map (clk=>clk, reset=>reset,D=> go_to_ones_1, Q=> ones_1 );
ones_2_ff : dflipflop port map (clk=>clk, reset=>reset,D=> go_to_ones_2, Q=> ones_2 );
ones_3_ff : dflipflop port map (clk=>clk, reset=>reset,D=> go_to_ones_3, Q=> ones_3 );
ones_4_ff : dflipflop port map (clk=>clk, reset=>reset,D=> go_to_ones_4, Q=> ones_4 );
最后,添加组合逻辑以计算当前状态和输入信号的下一个状态&#39; w&#39;。由于它是一个非常简单的FSM,您只需要将FSM图形表示转换为VHDL代码:
go_to_init <= '0'; -- never go to init (only when reset='1')
go_to_zeros_1 <= (init or ones_1 or ones_2 or ones_3 or ones_4 ) and (not w);
go_to_zeros_2 <= zeros_1 and (not w);
go_to_zeros_3 <= zeros_2 and (not w);
go_to_zeros_4 <= (zeros_3 or zeros_4) and (not w);
go_to_ones_1 <= (init or zeros_1 or zeros_2 or zeros_3 or zeros_4) and w;
go_to_ones_2 <= ones_1 and w;
go_to_ones_3 <= ones_2 and w;
go_to_ones_4 <= (ones_3 or ones_4) and w;
z <= ones_4 or zeros_4;
答案 1 :(得分:0)
复位后,dflipflops的所有输出均为“0”。
if reset <= '0' then
Q <= '0';
所以,A,B,C,D,E,F,G,H和I都在'0'。
由于分配Yn信号的布尔逻辑,Yn将始终为'0'。
E.g。
Y2 <= ((not w) and A); -- A is at '0' => Y2 will always be '0'.
输出'z'将始终为'0':
z <= (Y6 OR Y9); -- Y6 is always '0', Y9 is always '0' => Z will always be '0'.
顺便说一句:注册组件的输出是一个很好的设计规则。我会将z <= (Y6 OR Y9);
放在流程中。
重置后dflipflop的输出是否必须为'1?
答案 2 :(得分:0)
我会为这么小的任务编写更易读的代码:
library ieee;
use ieee.std_logic_1164.all;
entity part1 is
port (
clk : in std_logic;
w : in std_logic;
reset_n : in std_logic; -- mark low active signals with suffix _n
z : out std_logic
);
end part1;
architecture rtl of part1 is
signal sreg : std_logic_vector(3 downto 0);
begin
process
begin
wait until rising_edge( clk);
-- shift register
sreg <= sreg(2 downto 0) & w;
if sreg = "0000" or sreg = "1111" then
z <= '1';
else
z <= '0';
end if;
-- do we really need a reset?
if reset_n = '0' then
sreg <= "0000";
end if;
end process;
end architecture rtl;