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:
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:
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.