fpga – Fibonacci LFSR using the Altera Megafunction LPM_SHIFTREG – how to initialise? [VHDL]


I am having a frustrating time designing a linear feedback shift register where there is a need to use Altera’s LPM’s, in this case the LPM_SHIFTREG. This must be used as I have an assignment and exam on these components within days of writing this and of course have put this on the backburner for a while, so I appreciate if I could get some help to initialise and correctly configure the code.

The main code is instantiated within a top level component among other things, which are working correctly, so I have included the least amount of code needed to test this as a MWE. Right now I have no way of telling if any bits are shifted as the output is all zeros – obviously a LFSR would just feedback all zeros, so maybe without an initial state of some 1’s and 0’s it could be shifting zeros. So through my own work I have tried to use an initialise state, such that the lfsr_out will have some bits XOR as feedback to the lfsr_in. I have tried adding a reset state that should initialise for some time and then let the output of the LFSR take over and away it should go. This was not the case, so the following error occurs with the initialisation process:

enter image description here

Yes, I understand I cannot drive many inputs at the same time so how can I overcome this? I have tried looking at VHDL LFSR’s but with the use of the LPMs, which there are hardly any examples of such. Ideally, I would need to keep the LPM_SHIFTREG as this component is on an exam question, so I would like some peace of mind that I will not write complete rubbish! Here is a screenshot of the ModelSim signals for the current code where the initialisation process is removed:
enter image description here


ASK_modulator.vhd

library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
library altera_mf;
library lpm;
use lpm.lpm_components.ALL;

entity ASK_modulator is
    PORT (
        clk     : in std_logic;
        data_in  : in std_logic_vector(7 downto 0);
        pa_in    : in std_logic_vector(7 downto 0);
        data_out : out std_logic_vector(7 downto 0)
    );
end ASK_modulator;

architecture ASK_modulator_bhv of ASK_modulator 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);

    process(clk)
    begin
        if rising_edge(clk) then
            -- ASK modulation: If the LFSR output is '1', modulate the data; otherwise, output zero
            data_out <= (others => '0');
            data_out(7) <= data_in(7) and lfsr_out(9);
            data_out(6) <= data_in(6) and lfsr_out(9);
            data_out(5) <= data_in(5) and lfsr_out(9);
            data_out(4) <= data_in(4) and lfsr_out(9);
            data_out(3) <= data_in(3) and lfsr_out(9);
            data_out(2) <= data_in(2) and lfsr_out(9);
            data_out(1) <= data_in(1) and lfsr_out(9);
            data_out(0) <= data_in(0) and lfsr_out(9);
        end if;
    end process;
    
end ASK_modulator_bhv;

ASK_top.vhd

library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.ALL;

entity ASK_DDS_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_full_cyc : out std_logic_vector(7 downto 0)
   );
end ASK_DDS_top;

architecture ASK_DDS_top_bhv of ASK_DDS_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 LUT_comp
      PORT (
         CLK      : IN STD_LOGIC := '1';
         DATA_IN  : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
         DATA_OUT : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
      );
   end component;

   component ASK_modulator
      PORT (
         clk         : in std_logic;
         data_in     : in std_logic_vector(7 downto 0);
     pa_in       : in std_logic_vector(7 downto 0);
         data_out    : out std_logic_vector(7 downto 0)
      );
   end component;

   signal pa_data_out    : std_logic_vector(7 downto 0) := (others => '0');
   signal lut_data_out   : std_logic_vector(7 downto 0) := (others => '0');
   signal ask_data_out   : std_logic_vector(7 downto 0) := (others => '0');

begin

   -- Phase Accumulator
   phase_acc : PA_comp
      PORT MAP (
         CLK      => clk,
         FSW      => fsw_in,
         DATA_OUT => pa_data_out
      );
        
    pa_probe_out <= pa_data_out;
   
   -- Lookup Table
   lut_rom_f : LUT_comp
      PORT MAP (
         CLK      => clk,
         DATA_IN  => pa_data_out,
         DATA_OUT => lut_data_out
      );

   -- ASK Modulator
   ask_mod : ASK_modulator
      PORT MAP (
         clk         => clk,
         data_in     => lut_data_out,
     pa_in       => pa_data_out,
         data_out    => ask_data_out
      );

   -- Connect ASK_modulator to Output
   data_out_full_cyc <= ask_data_out;

end ASK_DDS_top_bhv;

PA_comp.vhd

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;

Note that the LUT component is not needed, I just need to verify that the LFSR will work as intended.



Source link

Leave a Comment