Генератор псевдослучайных чисел, использующий LFSR в VHDL
У меня возникли проблемы с созданием prng с использованием метода lfsr. Вот мой код:
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 считывает начальное число. Однако, и это мой вопрос, по какой-то причине временный сигнал только XOR содержит биты сигнала 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 ответ
Я сделал несколько небольших изменений в том, что у вас было (хотя вы в значительной степени там); Я не думаю, что LFSR поступил бы правильно в противном случае. Я добавил сигнал включения в LFSR, чтобы вы могли эффективно контролировать, когда вы хотите, чтобы он шагнул. Результирующий сим здесь.
Так же, как sidenote, вы также можете включить load
а также seed
входные данные, если вы хотите заполнить LFSR другим значением (вместо того, чтобы делать его константным).
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;
И тб:
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;