Here i am posting a snapshot of prbs
My code for prbs module is
-- Module Name: prbs - Behavioral
-- Project Name: modulator
-- Description:
--To make it of N bit replace existing value of N with desired value of N
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity prbs is
Port ( pclock : in STD_LOGIC;
preset : IN std_logic := '0';
prbsout : out STD_LOGIC);
end prbs;
architecture Behavioral of prbs is
COMPONENT dff is
PORT(
dclock : IN std_logic;
dreset : IN std_logic;
din : IN std_logic ;
dout : OUT std_logic
);
END COMPONENT;
signal dintern : std_logic_vector (4 downto 1); --Change value of N to change size of shift register
signal feedback : std_logic := '0';
begin
instdff : dff port map (pclock , preset , feedback , dintern(1));
genreg : for i in 2 to 4 generate --Change Value of N Here to generate that many instance of d flip flop
begin
instdff : dff port map ( pclock , preset , dintern(i-1) , dintern(i));
end generate genreg;
main : process(pclock)
begin
if pclock'event and pclock = '1' then
if preset = '0' then
if dintern /= "0" then
feedback <= dintern(1) xor dintern(3); -- For N equals four;
--feedback <= dintern(4) xor dintern(5) xor dintern(6) xor dintern(8); -- For N equals eight;
--feedback <= dintern(11) xor dintern(13) xor dintern(14) xor dintern(16); -- For N equals sixteen;
--feedback <= dintern(1) xor dintern(2) xor dintern(22) xor dintern(32); -- For N equals thirty two
else
feedback <= '1';
end if;
end if;
end if;
end process main;
prbsout <= dintern(4) ; --Change Value of N Here to take output to top entity
end Behavioral;
In it i am instantiating a d flip flop module
d ff module code
----------------------------------------------------------------------------------
-- Module Name: dff - Behavioral
-- Project Name:
-- Description:
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity dff is
Port ( dclock : in STD_LOGIC ;
dreset : in STD_LOGIC ;
din : in STD_LOGIC;
dout : out STD_LOGIC);
end dff;
architecture Behavioral of dff is
begin
process(dclock)
begin
if dclock'event and dclock = '1' then
if dreset = '0' then
dout <= din;
else
dout <= '1';
end if;
end if;
end process;
end Behavioral;
But i am not getting desired output. In top level entity i am getting always 1 at prbsout signal.
When i try to simulate then prbsout signal becomes undefined.
What i am missing?
The prbs
module reset at preset
does not apply to the feedback
signal,
probably because the intention was to use the initial value of 0 assigned in
the declaration of the feedback
signal. However, since the dff
modules
uses synchronous reset, and the dintern
signal will be undriven U
at start,
and since then next value for feedback
is calculated using dintern(1)
in an
xor, the feedback will get undefined right after start, and can't recover,
even if a lengthy reset is applied. See waveform from ModelSim below.
An immediate fix for the reset issue is to apply reset for feedback
also in
the main
process:
...
else -- preset /= '0'
feedback <= '0';
...
Now at least reset works, and can make the prbs
generate a sequence. See
waveform below.
Just a few additional comments to the code, while at it:
Instead of dclock'event and dclock = '1'
you can use rising_edge(dclock)
,
which I think must reader will find easier to understand, and it is less
error prone
For most tools, it is unnecessary to make a separte module just for a
flip-flop, like the dff
module, since the tools can infer flip-flop
directly from the process even when advanced expressions are used for signal
assignments are used.
But, I don't think the output is what you actually want. Based on your design, and the selected taps for the LFSR, it looks like you want to generate maximum length LFSR sequences, that is sequences with a length of 2 ** N - 1 for a LFSR register being N bits long.
The principles of LFSR and the taps to for feedback generation is described on Wikipedia: Linear feedback shift register.
However, since the feedback
signal is generated as a flip-flop, it becomes
part of the LSFR shift register, thus adds a bit to the length, but the tap
values are based on the dintern
part of the LFSR only, the taps will be
wrong. Selecting the wrong bits will result in a LFSR sequence that is less
than then maximum sequence, and you can also see that in the simulation output,
where the sequence is only 6 cycles long, even through the dintern(4 downto
1)
+ feedback
together makes a 5 bit register.
So a more thorough rewrite of the prbs
module is required, if what you want
is to generate maximum length PRBS sequences, and below is an example of how
the prbs
module can be written:
library ieee;
use ieee.std_logic_1164.all;
entity prbs_new is
generic(
BITS : natural);
port(
clk_i : in std_logic;
rst_i : in std_logic;
prbs_o : out std_logic);
end entity;
library ieee;
use ieee.numeric_std.all;
architecture syn of prbs_new is
signal lfsr : std_logic_vector(BITS downto 1); -- Flip-flops with LFSR state
function feedback(slv : std_logic_vector) return std_logic is -- For maximum length LFSR generation
begin
case slv'length is
when 3 => return slv( 3) xor slv( 2);
when 4 => return slv( 4) xor slv( 3);
when 8 => return slv( 8) xor slv( 6) xor slv( 5) xor slv(4);
when 16 => return slv(16) xor slv(15) xor slv(13) xor slv(4);
when 32 => return slv(32) xor slv(22) xor slv( 2) xor slv(1);
when others => report "feedback function not defined for slv'lenght as " & integer'image(slv'length)
severity FAILURE;
return 'X';
end case;
end function;
begin
process (clk_i, rst_i) is
begin
if rising_edge(clk_i) then
if unsigned(lfsr) /= 0 then
lfsr <= lfsr(lfsr'left - 1 downto lfsr'right) & feedback(lfsr); -- Left shift with feedback in
end if;
end if;
if rst_i = '1' then -- Asynchronous reset
lfsr <= std_logic_vector(to_unsigned(1, BITS)); -- Reset assigns 1 to lfsr signal
end if;
end process;
prbs_o <= lfsr(BITS); -- Drive output
end architecture;
Comments to ´prbs_new´ module
Generic BITS is added so diffrent LFSR length can be made from the same code.
Ports are named with "_i" for inputs and "_o" for outputs, since this naming convension is very useful when tracing signals at a toplevel with multiple modules.
The VHDL standard package ieee.numeric_std
is used instead of
the non-standard package ieee.std_logic_unsigned
.
Asynchronous reset is used instead of synchronous reset and initial value in the signal declaration.
The advantage over synchronous reset is that asynchronous reset typical applies to a dedicated input on the flip-flops in FPGA and ASIC technology, and not in the potentially timing critical data path, whereby the design can be faster.
The advantage over initial value in the signal declation is that FPGA and ASIC technologies are more likely to be able to implement this; there are cases where initial values are not supported. Also functional reset makes restart possible in a test bench without having to reload the simulator.
There is no check for an all-0 value of the lfsr
signal in the process,
since the lfsr
will never get an all-0 value if proper maximum length taps
are used, and the lfsr
signal is reset to a non-0 value.