在VHDL中使用LFSR的伪随机数生成器 [英] Pseudo Random Number Generator using LFSR in VHDL

查看:312
本文介绍了在VHDL中使用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信号的位进行XOR.它在第一个时钟脉冲上仍未定义.这是为什么?如果它在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;

解决方案

我对您所拥有的内容进行了一些细微的修改(尽管您已经很多了);我认为LFSR不会正确地采取其他措施.我向LFSR添加了启用信号,以便您可以有效地控制何时步进.生成的SIM卡是此处.

作为一个附带说明,如果要为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;

I'm having a bit of trouble creating a prng using the lfsr method. Here is my code:

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;

Here is the simulation I have ran: prng sim

Firstly, the check output is just there so I can monitor the output of the temp signal. Secondly, the line that is commented out is what is causing the problem.

As can be seen from the simulation, on the first rising edge of the clock, the Qt signal reads the seed. However, and this is my question, for some reason the temp signal only XORs the bits of the Qt signal on the second rising edge of the clock. It remains undefined on the first clock pulse. Why is that? If it operated on the first rising edge right after the Qt signal reads the seed, then I could uncomment the line that shifts the bits and it would solve my problem. Any help would be much appreciated!

Here is the test bench if anyone cares:

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;

解决方案

I made some slight modifications to what you had (you are pretty much there though); I don't think the LFSR would step properly otherwise. I added an enable signal to the LFSR so you can effectively control when you want it to step. Resulting sim is here.

Just as a sidenote, you could also include a load and seed inputs if you wanted to seed the LFSR with a different value (instead of making it const).

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;

And 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;

这篇关于在VHDL中使用LFSR的伪随机数生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆