Forum Discussion
Altera_Forum
Honored Contributor
14 years ago --- Quote Start --- basically the module takes a number 0-31 as a parameter, and in that module I have to translate that into a 32b std_logic_vector of pre-determined value (which is used as a mask). If there's a more 'VHDL' way to do this, lay it on me! 8-} --- Quote End --- Use a function to initialize a constant array. You could just use a function, however, if that function is inside a process statement, then it gets called each time the process gets called. If you use a function to initialize a constant, and then use the constant inside the process, then it all works nicely. For an example, check out this pseudo-random binary sequence generator code; http://www.ovro.caltech.edu/~dwh/correlator/pdf/lfsr_tutorial.pdf (http://www.ovro.caltech.edu/%7edwh/correlator/pdf/lfsr_tutorial.pdf) http://www.ovro.caltech.edu/~dwh/correlator/pdf/lfsr_tutorial_src.zip (http://www.ovro.caltech.edu/%7edwh/correlator/pdf/lfsr_tutorial_src.zip) The following are code snippets from prbs.vhd
-- ------------------------------------------------------------
-- Types
-- ------------------------------------------------------------
--
-- Transition matrix data type
--
-- * 2*DATA_WIDTH x LFSR_WIDTH
-- * the first DATA_WIDTH entries are used during reset
-- * the second DATA_WIDTH entries are used to determine
-- the next state (XOR feedback)
--
type prbs_matrix_t is array(0 to 2*DATA_WIDTH-1) of
std_logic_vector(LFSR_WIDTH-1 downto 0);
-- ------------------------------------------------------------
-- Functions
-- ------------------------------------------------------------
--
-- Transition matrix initialization
function prbs_matrix_init return prbs_matrix_t is
variable a : prbs_matrix_t;
begin
for i in 0 to 2*DATA_WIDTH-1 loop
if (i < LFSR_WIDTH) then
-- Identity matrix in the first LFSR entries
a(i) := (others => '0');
a(i)(i) := '1';
else
-- Calculate each row as the modulo-2 sum of
-- the previous the rows with bits set in the
-- generator polynomial, i.e., bits set in
-- positions 1 through LFSR_WIDTH.
--
a(i) := (others => '0');
for j in 1 to LFSR_WIDTH loop
if (POLYNOMIAL(j) = '1') then
a(i) := a(i) xor a(i-j);
end if;
end loop;
end if;
end loop;
return a;
end function;
-- PRBS output bit
--
-- Calculate the PRBS output bit sum using the transition
-- matrix row value (mask) and the LFSR state bits.
--
function prbs_sum_bit (
mask : std_logic_vector(LFSR_WIDTH-1 downto 0);
state : std_logic_vector(LFSR_WIDTH-1 downto 0)) return std_logic is
variable b : std_logic;
begin
-- Calculate an xor sum
b := '0';
for i in 0 to LFSR_WIDTH-1 loop
if (mask(i) = '1') then
b := b xor state(i);
end if;
end loop;
return b;
end function;
-- ------------------------------------------------------------
-- Signals
-- ------------------------------------------------------------
--
-- PRBS/LFSR data
signal data : std_logic_vector(DATA_WIDTH-1 downto 0);
begin
-- ------------------------------------------------------------
-- PRBS/LFSR register
-- ------------------------------------------------------------
--
process(clk, rstN)
constant reset_seed :
std_logic_vector(LFSR_WIDTH-1 downto 0) :=
(others => '1');
constant prbs_matrix : prbs_matrix_t := prbs_matrix_init;
begin
if (rstN = '0') then
-- LFSR state bits reset to all ones
data(LFSR_WIDTH-1 downto 0) <= reset_seed;
-- The remaining output bits are calculated using
-- the transition matrix (PRBS sums). The all-ones
-- reset seed is used to determine output bits that
-- are set or clear;
--
-- * output bits with an even number of xor terms
-- get set to zero
-- * bits with an odd number of xor terms get set
-- to one
--
if (PRBS_WIDTH > LFSR_WIDTH) then
for i in LFSR_WIDTH to PRBS_WIDTH-1 loop
data(i) <=
prbs_sum_bit(prbs_matrix(i), reset_seed);
end loop;
end if;
elsif rising_edge(clk) then
if (load = '1') then
-- LFSR state bits get loaded with seed
data(LFSR_WIDTH-1 downto 0) <= seed;
-- Others bits calculated based on seed
if (PRBS_WIDTH > LFSR_WIDTH) then
for i in LFSR_WIDTH to PRBS_WIDTH-1 loop
data(i) <=
prbs_sum_bit(prbs_matrix(i), seed);
end loop;
end if;
elsif (enable = '1') then
-- PRBS parallel output update
-- * the current LFSR state is encoded in
-- data(LFSR_WIDTH-1 downto 0)
-- * the next PRBS output is PRBS_WIDTH states
-- further on from the current state.
--
for i in 0 to DATA_WIDTH-1 loop
data(i) <=
prbs_sum_bit(prbs_matrix(i+PRBS_WIDTH),
data(LFSR_WIDTH-1 downto 0));
end loop;
end if;
end if;
end process;
-- LFSR state output
lfsr_q <= data(LFSR_WIDTH-1 downto 0);
-- PRBS parallel output
prbs_q <= data(PRBS_WIDTH-1 downto 0);
end architecture;
Download the code and look at it with syntax high-lighting. The key thing to note is the use of a function to initialize a constant. That constant changes depending on generics. These functions do not synthesize to anything. They essentially use the pre-processor to do some work (initialize an array with 1's and 0's), and its the logic associated with the final array that Quartus has to synthesize. Cheers, Dave