我在设计线性反馈移位寄存器时遇到了令人沮丧的问题,其中需要使用 Altera 的 LPM,在本例中为 LPM_SHIFTREG。这必须被使用,因为我在写这篇文章的几天内就对这些组件进行了作业和考试,当然已经把它放在次要位置一段时间了,所以如果我能得到一些帮助来初始化和正确配置代码,我将不胜感激.
主要代码在顶级组件中实例化,并且运行正常,因此我包含了测试 MWE 所需的最少量的代码。现在我无法判断是否有任何位被移位,因为输出全为零 - 显然 LFSR 只会反馈全零,所以也许没有一些 1 和 0 的初始状态,它可能会移位零。因此,通过我自己的工作,我尝试使用初始化状态,以便
lfsr_out
将有一些位异或作为对 lfsr_in
的反馈。我尝试添加一个重置状态,该状态应该初始化一段时间,然后让 LFSR 的输出接管并离开它。事实并非如此,因此在初始化过程中发生以下错误:
是的,我知道我无法同时驱动多个输入,那么我该如何克服这个问题?我曾尝试查看 VHDL LFSR,但使用了 LPM,但几乎没有这样的例子。理想情况下,我需要保留 LPM_SHIFTREG,因为这个组件是在考试问题上,所以我想放心,我不会写完全垃圾!以下是当前代码的 ModelSim 信号的屏幕截图,其中
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
library altera_mf;
library lpm;
use lpm.lpm_components.ALL;
entity LFSR_comp is
PORT (
clk : in std_logic;
pa_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(9 downto 0)
);
end LFSR_comp;
architecture LFSR_comp_bhv of LFSR_comp is
signal lfsr_in : std_logic := '0';
signal lfsr_out : std_logic_vector(9 downto 0);
signal lfsr_clock : std_logic := '0';
signal lfsr_rst : std_logic := '1';
signal initial_state : std_logic_vector(9 downto 0) := "1010110111";
begin
-- Toggle the lfsr_clock using PA as a clk divider
lfsr_clock <= pa_in(7);
-- Initialization process
-- process(lfsr_in, lfsr_rst, lfsr_out, initial_state)
-- begin
-- if lfsr_rst = '1' then
-- lfsr_out <= initial_state;
-- lfsr_rst <= '0';
-- end if;
-- end process;
-- Load the initial state into the shift register
lfsr : LPM_SHIFTREG
generic map (
LPM_WIDTH => 10,
LPM_DIRECTION => "LEFT"
)
port map (
data => lfsr_out,
clock => lfsr_clock,
q => lfsr_out,
shiftin => lfsr_in
);
lfsr_in <= lfsr_out(7) xor lfsr_out(3) xor lfsr_out(2) xor lfsr_out(0);
data_out <= lfsr_out;
end LFSR_comp_bhv;
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.ALL;
entity LFSR_top is
PORT (
clk : in std_logic;
fsw_in : in std_logic_vector(7 downto 0);
pa_probe_out : out std_logic_vector(7 downto 0);
data_out : out std_logic_vector(9 downto 0)
);
end LFSR_top;
architecture LFSR_top_bhv of LFSR_top is
component PA_comp
PORT (
CLK : IN STD_LOGIC := '1';
FSW : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
DATA_OUT : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
end component;
component LFSR_comp
PORT (
CLK : in std_logic;
PA_IN : in std_logic_vector(7 downto 0);
DATA_OUT : out std_logic_vector(9 downto 0)
);
end component;
signal pa_data_out : std_logic_vector(7 downto 0) := (others => '0');
signal ask_data_out : std_logic_vector(9 downto 0) := (others => '0');
begin
-- Phase Accumulator
phase_acc : PA_comp
PORT MAP (
CLK => clk,
FSW => fsw_in,
DATA_OUT => pa_data_out
);
-- LFSR
lfsr : LFSR_comp
PORT MAP (
CLK => clk,
PA_IN => pa_data_out,
DATA_OUT => ask_data_out
);
data_out <= ask_data_out;
end LFSR_top_bhv;
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
library altera_mf;
library lpm;
use lpm.lpm_components.ALL;
entity PA_comp is
PORT (
clk : in std_logic;
fsw : in std_logic_vector(7 downto 0); -- Assuming an 8-bit FTW
data_out : out std_logic_vector(7 downto 0)
);
end PA_comp;
architecture PA_comp_bhv of PA_comp is
signal add_out : std_logic_vector(7 downto 0) := (others => '0');
signal q_out : std_logic_vector(7 downto 0) := (others => '0');
begin
-- LPM_ADD_SUB for phase accumulator
addnsub : lpm_add_sub
GENERIC MAP (
LPM_WIDTH => 8,
LPM_DIRECTION => "ADD"
)
PORT MAP (
DATAA => fsw,
DATAB => q_out,
RESULT => add_out
);
-- LPM_FF for phase accumulator
dff : lpm_ff
GENERIC MAP (
LPM_WIDTH => 8,
LPM_FFTYPE => "DFF"
)
PORT MAP (
DATA => add_out,
CLOCK => clk,
Q => q_out
);
data_out <= q_out;
end PA_comp_bhv;
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.ALL;
entity LFSR_tb is
end LFSR_tb;
architecture LFSR_tb_bhv of LFSR_tb is
signal clk : std_logic := '0';
signal fsw_in : std_logic_vector(7 downto 0) := (others => '0');
signal pa_probe_out : std_logic_vector(7 downto 0) := (others => '0');
signal data_out : std_logic_vector(9 downto 0) := (others => '0');
constant clk_period : time := 10 ns;
begin
uut: entity work.LFSR_top
port map (
clk => clk,
fsw_in => fsw_in,
pa_probe_out => pa_probe_out,
data_out => data_out
);
-- Clock process def.
clk_process : process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
stimulus_process: process
begin
fsw_in <= "00000001";
wait for 2560 ns;
end process;
end LFSR_tb_bhv;
-- Quartus II 9.1 Build 222 10/21/2009
220model.vhd,实体lpm.LPM_SHIFTREG,有一个预设值,通用lpm_pvalue。不会出现在您链接的文档中,它位于 VHDL 源代码中。英特尔可能不鼓励将其用于某些设备系列,因为这些设备系列不方便或不可能操纵宏 LPM_SHIFTREG 中使用的单元触发器的数据输入和输出的极性。更改使用预设值:
library IEEE;
use IEEE.std_logic_1164.ALL;
-- use IEEE.numeric_std.ALL; -- CHANGED no declarations used
-- library altera_mf; -- CHANGED no declarations used
library lpm;
use lpm.lpm_components.ALL;
entity LFSR_comp is
PORT (
clk : in std_logic;
pa_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(9 downto 0)
);
end LFSR_comp;
architecture LFSR_comp_bhv of LFSR_comp is
signal lfsr_in : std_logic := '0';
signal lfsr_out : std_logic_vector(9 downto 0);
signal lfsr_clock : std_logic := '0';
-- signal lfsr_rst : std_logic := '1'; -- CHANGED NOT USED
-- CHANGED SHOULD BE A CONSTANT:
-- signal initial_state : std_logic_vector(9 downto 0) := "1010110111";
begin
-- Toggle the lfsr_clock using PA as a clk divider
lfsr_clock <= pa_in(7);
-- Initialization process
-- process(lfsr_in, lfsr_rst, lfsr_out, initial_state)
-- begin
-- if lfsr_rst = '1' then
-- lfsr_out <= initial_state;
-- lfsr_rst <= '0';
-- end if;
-- end process;
-- Load the initial state into the shift register
lfsr : LPM_SHIFTREG
generic map (
LPM_WIDTH => 10,
LPM_DIRECTION => "LEFT", -- CHANGED ADDED comma separeator
LPM_PVALUE => "1010110111" -- CHANGED ADDED preset value
)
port map (
data => lfsr_out,
clock => lfsr_clock,
q => lfsr_out,
shiftin => lfsr_in
);
lfsr_in <= lfsr_out(7) xor lfsr_out(3) xor lfsr_out(2) xor lfsr_out(0);
data_out <= lfsr_out;
end LFSR_comp_bhv;
还要注意注释掉的 use 子句,其声明在源代码中不被依赖。其他源代码文件中可能还有其他情况。瞧瞧,改变起作用了!
如果您在使用 lpm_pvalue 时遇到工具限制,有两种选择:使用 sset 和 lpm_svalue 或 aset 和 lpm_avalue。实施工作几乎相同:
architecture LFSR_comp_aset of LFSR_comp is
signal lfsr_in : std_logic := '0';
signal lfsr_out : std_logic_vector(9 downto 0);
signal lfsr_clock : std_logic := '0';
signal lfsr_rst : std_logic := '1';
-- CHANGED SHOULD BE A CONSTANT:
-- signal initial_state : std_logic_vector(9 downto 0) := "1010110111";
begin
-- Toggle the lfsr_clock using PA as a clk divider
lfsr_clock <= pa_in(7);
-- Initialization process
-- process(lfsr_in, lfsr_rst, lfsr_out, initial_state)
-- begin
-- if lfsr_rst = '1' then
-- lfsr_out <= initial_state;
-- lfsr_rst <= '0';
-- end if;
-- end process;
LFSR_RESET:
process
begin
wait on clk;
if rising_edge(clk) then
if lfsr_rst = '1' then
lfsr_rst <= '0';
end if;
end if;
wait;
end process;
-- Load the initial state into the shift register
lfsr : LPM_SHIFTREG
generic map (
LPM_WIDTH => 10,
LPM_DIRECTION => "LEFT", -- CHANGED ADDED comma separeator
LPM_AVALUE => "1010110111" -- CHANGED ADDED preset value
)
port map (
aset => lfsr_rst, -- CHANGED non-default value for port in
data => lfsr_out,
clock => lfsr_clock,
q => lfsr_out,
shiftin => lfsr_in
);
lfsr_in <= lfsr_out(7) xor lfsr_out(3) xor lfsr_out(2) xor lfsr_out(0);
data_out <= lfsr_out;
end LFSR_comp_aset;
在使用 sset 时,可以考虑 lfsr_rst 的一个时钟延迟会对 pa_comp 产生扭曲影响。无论如何:
这也有效。 aset信号在这里可能很难看到,它在clk的第一个上升沿后消失。
对于您的学校项目来说,LPM_FF 是否适合使用 Riding_edge(clk) 测试来推断时序逻辑?