在VHDL中使用LFSR的伪随机数发生器

时间:2017-03-28 22:27:38

标签: random numbers vhdl generator lfsr

使用lfsr方法创建prng时遇到了一些麻烦。这是我的代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pseudorng is
Port ( clock : in STD_LOGIC;
       reset : in STD_LOGIC;
       Q : out STD_LOGIC_VECTOR (7 downto 0);
       check: out STD_LOGIC);

       constant seed: STD_LOGIC_VECTOR(7 downto 0) := "00000001";
end pseudorng;

architecture Behavioral of pseudorng is

signal temp: STD_LOGIC;
signal Qt: STD_LOGIC_VECTOR(7 downto 0);

begin

PROCESS(clock)
BEGIN

IF rising_edge(clock) THEN
IF (reset='1') THEN Qt <= "00000000";
ELSE Qt <= seed; 
END IF;
temp <= Qt(4) XOR Qt(3) XOR Qt(2) XOR Qt(0);
--Qt <= temp & Qt(7 downto 1);

END IF;
END PROCESS;

check <= temp;
Q <= Qt;

end Behavioral;

这是我运行的模拟: prng sim

首先,检查输出就在那里,所以我可以监视临时信号的输出。其次,被注释掉的那一行是导致问题的原因。

从仿真可以看出,在时钟的第一个上升沿,Qt信号读取种子。然而,这是我的问题,由于某种原因,临时信号仅在时钟的第二个上升沿对Qt信号的位进行异或。它在第一个时钟脉冲上仍未定义。这是为什么?如果它在Qt信号读取种子后立即在第一个上升沿操作,那么我可以取消注释移位的行,这将解决我的问题。任何帮助将不胜感激!

如果有人关心,这是测试台:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb_pseudorng is
end tb_pseudorng;

architecture bench of tb_pseudorng is

COMPONENT pseudorng
      Port ( clock : in STD_LOGIC;
      reset : in STD_LOGIC;
      Q : out STD_LOGIC_VECTOR (7 downto 0);
      check: out STD_LOGIC);
END COMPONENT;

signal clock1: STD_LOGIC;
signal reset1: STD_LOGIC;
signal Q1: STD_LOGIC_VECTOR(7 downto 0);
signal check1: STD_LOGIC;

begin

mapping: pseudorng PORT MAP(
clock => clock1,
reset => reset1,
Q => Q1,
check => check1);

clock: PROCESS
BEGIN
clock1<='0'; wait for 50ns;
clock1<='1'; wait for 50ns;
END PROCESS;

reset: PROCESS
BEGIN
reset1<='0'; wait for 900ns;
END PROCESS; 

end bench;

1 个答案:

答案 0 :(得分:2)

我对你所拥有的东西进行了一些细微的修改(尽管你很漂亮);我不认为LFSR会采取其他措施。我向LFSR添加了一个启用信号,因此您可以有效地控制何时需要它。结果sim是here

正如旁注所示,如果您希望使用不同的值(而不是使其为const)为LFSR播种,则还可以包含loadseed输入。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pseudorng is
Port ( clock : in STD_LOGIC;
       reset : in STD_LOGIC;
       en : in STD_LOGIC;
       Q : out STD_LOGIC_VECTOR (7 downto 0);
       check: out STD_LOGIC);

--       constant seed: STD_LOGIC_VECTOR(7 downto 0) := "00000001";
end pseudorng;

architecture Behavioral of pseudorng is

--signal temp: STD_LOGIC;
signal Qt: STD_LOGIC_VECTOR(7 downto 0) := x"01";

begin

PROCESS(clock)
variable tmp : STD_LOGIC := '0';
BEGIN

IF rising_edge(clock) THEN
   IF (reset='1') THEN
   -- credit to QuantumRipple for pointing out that this should not
   -- be reset to all 0's, as you will enter an invalid state
      Qt <= x"01"; 
   --ELSE Qt <= seed;
   ELSIF en = '1' THEN
      tmp := Qt(4) XOR Qt(3) XOR Qt(2) XOR Qt(0);
      Qt <= tmp & Qt(7 downto 1);
   END IF;

END IF;
END PROCESS;
-- check <= temp;
check <= Qt(7);
Q <= Qt;

end Behavioral;

并且tb:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb_pseudorng is
end tb_pseudorng;

architecture bench of tb_pseudorng is

COMPONENT pseudorng
      Port ( clock : in STD_LOGIC;
      reset : in STD_LOGIC;
      en : in STD_LOGIC;
      Q : out STD_LOGIC_VECTOR (7 downto 0);
      check: out STD_LOGIC);
END COMPONENT;

signal clock1: STD_LOGIC;
signal reset1: STD_LOGIC;
signal Q1: STD_LOGIC_VECTOR(7 downto 0);
signal check1: STD_LOGIC;
signal en : STD_LOGIC;

begin

mapping: pseudorng PORT MAP(
clock => clock1,
reset => reset1,
en => en,
Q => Q1,
check => check1);

clock: PROCESS
BEGIN
   clock1 <= '0'; wait for 50 ns;
   clock1 <= '1'; wait for 50 ns;
END PROCESS;

reset: PROCESS
BEGIN
   reset1 <= '0';
   en <= '1';
   wait for 900 ns;
END PROCESS;

end bench;