我的PRN-Generator无法正常工作。我想用线性反馈移位寄存器来做。
模拟和编译工作没有问题,但输出错误(lfsr_out ='0')并且没有改变。
代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity lfsr_counter is
generic(
WIDTH : integer := 10
);
port(
clk : in std_logic; --clock
rst : in std_logic; --positiv rst
lfsr_out : out std_logic --1 bit output of lfsr
);
end lfsr_counter;
-------------------------------------------------------------------
architecture behavioral of lfsr_counter is
type state_type is (state_rst, state_go); --rst: reset; go: lfsr
shifts
signal present_state : state_type;
signal next_state : state_type;
signal lfsr : std_logic_vector((WIDTH - 1) downto 0) :=
(others => '0');
signal d0 : std_logic := '0';
--stores the current feedbackvalue
begin
--sequencial logic:
-------------------------------------------------------------------
state_register : process(clk, rst)
begin
if (rst = '1') then
present_state <= state_rst; --default state on reset.
elsif (rising_edge(clk)) then
present_state <= next_state; --state change
end if;
end process;
-- combinatorial logic
-------------------------------------------------------------------
comb_logic : process(present_state, rst)
begin
case present_state is
when state_rst =>
if (rst = '1') then
next_state <= state_rst;
else
next_state <= state_go;
end if;
when state_go =>
if (rst = '1') then
next_state <= state_rst;
else
next_state <= state_go;
end if;
end case;
end process;
output_logic : process(present_state)
begin
if (present_state = state_go) then
--assert ((WIDTH >= 3) and (WIDTH <= 10))
--report "Error: the LFSR width must be between 3 and 10" severity
failure;
case WIDTH is --definitions for the feedback
when 3 => d0 <= lfsr(2) xnor lfsr(1);
when 4 => d0 <= lfsr(3) xnor lfsr(2);
when 5 => d0 <= lfsr(4) xnor lfsr(2);
when 6 => d0 <= lfsr(5) xnor lfsr(4);
when 7 => d0 <= lfsr(6) xnor lfsr(5);
when 8 => d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor
lfsr(3);
when 9 => d0 <= lfsr(8) xnor lfsr(4);
when 10 => d0 <= lfsr(9) xnor lfsr(6);
when others => null;
end case;
lfsr <= std_logic_vector(unsigned(lfsr) sll 1); --shifting all
bits to left by 1
lfsr_out <= lfsr(WIDTH - 1); --MSB to output
lfsr <= lfsr(WIDTH - 1 downto 1) & d0; --concatenate the
feedback to the lfsr
else
lfsr <= (others => '0'); --reset state -> lfsr contains only
'0'
lfsr_out <= '0';
end if;
end process;
end architecture;
如果在output_logic中设置“lfsr_out&lt; ='1'”,则输出将保持为“1”。我的代码出了什么问题?
答案 0 :(得分:3)
我的代码出了什么问题?
您的移位寄存器的值为全0和XNOR将产生输出d0为'1'。这就是'1'的来源。
您可以使用generate语句生成d0而不是带有case语句的process语句。
对lfsr的第一次分配不起作用,可以删除。任何预定时间只有一个预计输出波形。没有后延迟的分配将产生增量循环。同一个delta周期中的两个和最后一个将生效。因此,您不需要包std_logic_unsigned(Synopsys)或numeric_std(IEEE)。
合成结果
lfsr不是一个时钟寄存器,它是一个组合循环,总是在合成硬件中产生'1'。这是由于缺乏顺序转移造成的。
此外,您的模拟如何正常运行?进程output_logic仅对present_state上的事件恢复。
抛弃单独的状态机并实现一个定时的lfsr移位寄存器并使用generate语句:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.numeric_std.all;
entity lfsr_counter is
generic (
-- WIDTH: integer := 10
WIDTH: positive range 3 to 10 := 10
);
port (
clk: in std_logic;
rst: in std_logic; -- positive rst
lfsr_out: out std_logic
);
end entity lfsr_counter;
architecture behavioral of lfsr_counter is
-- type state_type is (state_rst, state_go);
-- signal present_state: state_type;
-- signal next_state: state_type;
signal lfsr: std_logic_vector((WIDTH - 1) downto 0) := (others => '0');
signal d0: std_logic := '0';
begin
-- state_register:
-- process (clk, rst)
-- begin
-- if rst = '1' then
-- present_state <= state_rst;
-- elsif rising_edge(clk) then
-- present_state <= next_state;
-- end if;
-- end process;
-- comb_logic:
-- process (present_state, rst)
-- begin
-- case present_state is
-- when state_rst =>
-- if rst = '1' then
-- next_state <= state_rst;
-- else
-- next_state <= state_go;
-- end if;
-- when state_go =>
-- if rst = '1' then
-- next_state <= state_rst;
-- else
-- next_state <= state_go;
-- end if;
-- end case;
-- end process;
-- Using VHDL -2008 you could use a case generate or elsif
WIDTH3:
if WIDTH = 3 generate
d0 <= lfsr(2) xnor lfsr(1);
end generate;
WIDTH4:
if WIDTH = 4 generate
d0 <= lfsr(3) xnor lfsr(2);
end generate;
WIDTH5:
if WIDTH = 5 generate
d0 <= lfsr(4) xnor lfsr(2);
end generate;
WIDTH6:
if WIDTH = 6 generate
d0 <= lfsr(5) xnor lfsr(4);
end generate;
WIDTH7:
if WIDTH = 7 generate
d0 <= lfsr(6) xnor lfsr(5);
end generate;
WIDTH8:
if WIDTH = 8 generate
d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3);
end generate;
WIDTH9:
if WIDTH = 9 generate
d0 <= lfsr(8) xnor lfsr(4);
end generate;
WIDTH10:
if WIDTH = 10 generate
d0 <= lfsr(9) xnor lfsr(6);
end generate;
-- output_logic:
-- process (present_state)
-- begin
-- if present_state = state_go then
-- case WIDTH is
-- when 3 =>
-- d0 <= lfsr(2) xnor lfsr(1);
-- when 4 =>
-- d0 <= lfsr(3) xnor lfsr(2);
-- when 5 =>
-- d0 <= lfsr(4) xnor lfsr(2);
-- when 6 =>
-- d0 <= lfsr(5) xnor lfsr(4);
-- when 7 =>
-- d0 <= lfsr(6) xnor lfsr(5);
-- when 8 =>
-- d0 <= lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3);
-- when 9 =>
-- d0 <= lfsr(8) xnor lfsr(4);
-- when 10 =>
-- d0 <= lfsr(9) xnor lfsr(6);
-- when others =>
-- null;
-- end case;
-- -- lfsr <= lfsr sll 1;
-- lfsr_out <= lfsr(WIDTH - 1);
-- lfsr <= lfsr(WIDTH - 1 downto 1) & d0;
-- else
-- lfsr <= (others => '0');
-- lfsr_out <= '0';
-- end if;
-- end process;
lfsr_reg:
process (rst, clk)
begin
if rst = '1' then
lfsr <= (others =>'0');
elsif rising_edge(clk) then
lfsr <= lfsr(WIDTH - 2 downto 0) & d0; -- WAS WIDTH - 1 downto 1
end if;
end process;
lfsr_out <= lfsr(WIDTH - 1); -- not separately registered
end architecture;
带有generate语句的位没有任何意义,但是从合成中卸载工作,这必须在case语句多路复用器中使用所有这些赋值。
还有一个添加的测试平台来创建Minimal, Complete and Verifiable example,我们看到lfsr实际上并没有向左移动。修复程序显示在上面的代码中并涉及更改:
lfsr <= lfsr(WIDTH - 2 downto 0) & d0; -- WAS WIDTH - 1 downto 1
测试平台:
library ieee;
use ieee.std_logic_1164.all;
entity lfsr_counter_tb is -- a testbench
end entity;
architecture foo of lfsr_counter_tb is
constant WIDTH: positive range 1 to 10 := 10; -- test full length
signal clk: std_logic := '1';
signal rst: std_logic := '0';
signal lfsr_out: std_logic;
begin
DUT:
entity work.lfsr_counter
generic map (
WIDTH => WIDTH
)
port map (
clk => clk,
rst => rst,
lfsr_out => lfsr_out
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > 550 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 11 ns;
rst <= '1';
wait for 99 ns;
rst <= '0';
wait;
end process;
end architecture;
模拟:
lfsr_counter也应该合成并运行。
Uhhm。我们的数字设计课程从未听说过有关生成声明的任何内容!在某些情况下,这可能非常有用。谢谢你这个例子。我理解你的代码。它非常简单,自我解释。您还可以避免组合循环。但是,这是一种不同的方法。我仍然希望将其作为FSM来实现并理解FSM的机制。现在,我知道output_logic部分没有计时,这会导致梳理。环。此外,只执行lfsr的最后一个语句。我需要编辑什么才能使其正常工作?
他们说这是一个不同的问题。两个特别的,今天只有。
您的代码显示编程语言思维,而VHDL是硬件描述语言。例如,当任何进程尚未在当前模拟周期中恢复或随后暂停时,不会发生信号更新。这意味着d0不希望成为信号,或者它的分配想要处于单独的过程中。
信号在进程之间进行通信。对于仅在进程内使用的对象,如果在赋值后计算值,则应使用变量。
还有使用WIDTH分配d0的多路复用器。它代表了在合成过程中会被吃掉的硬件,因为WIDTH是不变的,作为通用常量传递。
泛型常量可以有一个定义的标量范围:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.numeric_std.all;
entity lfsr_counter is
generic (
-- WIDTH: integer := 10
WIDTH: positive range 3 to 10 := 10
);
port (
clk: in std_logic;
rst: in std_logic; -- positive rst
lfsr_out: out std_logic
);
end entity lfsr_counter;
这允许编写VHDL设计描述,而不必处理您使用的值之外的值。所有额外的逻辑都被吃掉了,但你可能会引入错误。
所以d0做了一个变量,WIDTH约束了,lsfr_out赋值转移到了一个并发语句:
architecture behave of lfsr_counter is
type state_type is (state_rst, state_go);
signal present_state: state_type;
signal next_state: state_type;
signal lfsr: std_logic_vector((WIDTH - 1) downto 0) := (others => '0');
-- signal d0: std_logic := '0';
begin
state_register:
process (clk, rst)
begin
if rst = '1' then
present_state <= state_rst;
elsif rising_edge(clk) then
present_state <= next_state;
end if;
end process;
comb_logic:
process (present_state, rst)
begin
case present_state is
when state_rst =>
if rst = '1' then
next_state <= state_rst;
else
next_state <= state_go;
end if;
when state_go =>
if rst = '1' then
next_state <= state_rst;
else
next_state <= state_go;
end if;
end case;
end process;
output_logic:
process (clk) -- (present_state)
variable d0: std_logic;
begin
if rising_edge(clk) then
if present_state = state_go then
case WIDTH is
when 3 =>
d0 := lfsr(2) xnor lfsr(1);
when 4 =>
d0 := lfsr(3) xnor lfsr(2);
when 5 =>
d0 := lfsr(4) xnor lfsr(2);
when 6 =>
d0 := lfsr(5) xnor lfsr(4);
when 7 =>
d0 := lfsr(6) xnor lfsr(5);
when 8 =>
d0 := lfsr(7) xnor lfsr(5) xnor lfsr(4) xnor lfsr(3);
when 9 =>
d0 := lfsr(8) xnor lfsr(4);
when 10 =>
d0 := lfsr(9) xnor lfsr(6);
-- when others =>
-- null;
end case;
-- lfsr <= lfsr sll 1;
-- lfsr_out <= lfsr(WIDTH - 1);
-- lfsr <= lfsr(WIDTH - 1 downto 1) & d0;
lfsr <= lfsr(WIDTH - 2 downto 0) & d0;
else
lfsr <= (others => '0'); -- a synchronous reset
-- lfsr_out <= '0';
end if;
end if;
end process;
lfsr_out <= lfsr(WIDTH - 1); -- not separately registered, a mux
end architecture behave;
显示第一个架构的所有更改,原始代码已注释掉。这使用相同的测试平台进行分析,详细说明和模拟,并产生相同的结果。
移动lfsr_out分配的原因基于与d0相同的问题,另一个观察结果。 output_logic进程只有在找到敏感列表的信号上有事件时才会恢复执行。
这意味着你会错过lfsr_out上的转换来模拟你的第一个设计,或者意味着使用一个带时钟的lfsr寄存器的半时钟延迟(对于下一个clk边缘),就像上面的行为架构一样。
您可以注意到lsfr赋值更改实际上提供了移位,如顶部代码示例中的lfsr_reg进程中所示。你会注意到lfsr的第一次分配仍然被注释掉了。