Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

generic shift register in vhdl

Status
Not open for further replies.

nats_

Newbie level 6
Joined
Apr 12, 2012
Messages
14
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,378
Hi all,

i searched to see if there were other threads that could help me solve this, but found nothing useful enough..
i'm new at VHDL, and i have a problem-
i'm supposed to create a generic shift register that also samples the the mid-values (as oppose to just the last output)
my problem is that for some reason (i'm probably doing something horribly wrong..) the DATA_OUT & DATA_OUT_FULL signals don't seem to be getting any values, or to respond to the Enable signal.

any help would be much appriciated :)

this is my code:

Code:
library IEEE;
use IEEE.std_logic_1164.all;

entity shift_register is
  generic (
    G_SHIFT_REGISTER_SIZE   : integer   :=  4;
    G_DATA_WIDTH            : integer   :=  8
  );
  port (
    CLK           : in  std_logic;
    RESET         : in  std_logic;
    Data_in       : in  std_logic_vector (G_DATA_WIDTH-1 downto 0);
    Enable        : in  std_logic;
    Data_out      : out std_logic_vector (G_DATA_WIDTH-1 downto 0);
    Data_out_full : out std_logic_vector (G_SHIFT_REGISTER_SIZE*G_DATA_WIDTH-1 downto 0)
  );
end entity shift_register;

architecture shift_register_arch of shift_register is
  
type t_shift_reg is array (G_SHIFT_REGISTER_SIZE-1 downto 0) of std_logic_vector (G_DATA_WIDTH-1 downto 0);

component shift_register is
  generic (
    G_SHIFT_REGISTER_SIZE   : integer   :=  4;
    G_DATA_WIDTH            : integer   :=  8
  );
  port (
    CLK           : in  std_logic;
    RESET         : in  std_logic;
    Enable        : in  std_logic;
    Data_in       : in  std_logic_vector (G_DATA_WIDTH-1 downto 0);
    Data_out      : out std_logic_vector (G_DATA_WIDTH-1 downto 0);
    Data_out_full : out std_logic_vector (G_SHIFT_REGISTER_SIZE*G_DATA_WIDTH-1 downto 0)
  );
end component shift_register;
   
signal connect_sig : std_logic_vector (G_DATA_WIDTH*(G_SHIFT_REGISTER_SIZE+1)-1 downto 0);
   
begin
  connect_sig(G_DATA_WIDTH-1 downto 0) <= Data_in;   
  
  shift_register_gen: for i in G_SHIFT_REGISTER_SIZE-1 downto 0 generate
  reg_u: shift_register
  port map (
   CLK => CLK,
   RESET => RESET,
   Enable => Enable,
   Data_in => connect_sig((i+1)*G_DATA_WIDTH-1 downto i*G_DATA_WIDTH),   
   Data_out => connect_sig((i+2)*G_DATA_WIDTH-1 downto (i+1)*G_DATA_WIDTH),
   --Data_out_full => connect_sig((i+2)*G_DATA_WIDTH-1 downto G_DATA_WIDTH)
 );
 end generate shift_register_gen;

-- Connecting outside the process
	--------------------------------------------------
data_out <= connect_sig(G_DATA_WIDTH*(G_SHIFT_REGISTER_SIZE+1)-1 downto G_DATA_WIDTH*(G_SHIFT_REGISTER_SIZE));	
Data_out_full <= connect_sig((G_SHIFT_REGISTER_SIZE+1)*G_DATA_WIDTH-1 downto G_DATA_WIDTH);
 
 shift_reg_proc: process (CLK, RESET, Enable)
 begin
  
 if (RESET = '1') then   --a-synchronous reset
   for i in G_SHIFT_REGISTER_SIZE-1 downto 0 LOOP
   connect_sig(i+G_DATA_WIDTH) <= '0';   
   end LOOP;
  
 elsif (RESET = '0') then
   if (clk'Event and CLK = '1') then
     if (Enable = '1') then
     for i in G_DATA_WIDTH*(G_SHIFT_REGISTER_SIZE+1)-1 downto G_DATA_WIDTH LOOP
     connect_sig(i) <= connect_sig(i-1);
     end LOOP;
     for i in G_DATA_WIDTH-1 downto 0 LOOP
     connect_sig(i) <= Data_in(i);
     end LOOP;
     for i in G_DATA_WIDTH*(G_SHIFT_REGISTER_SIZE+1)-1 downto G_DATA_WIDTH LOOP
     Data_out_full(i-G_DATA_WIDTH) <= connect_sig(i); 
     end LOOP;
     for i in G_DATA_WIDTH-1 downto 0 LOOP
     Data_out(i) <= connect_sig(i+G_DATA_WIDTH*G_SHIFT_REGISTER_SIZE-1);
     end LOOP;
     
    end if;
   end if;
 end if;
 
end process shift_reg_proc;
 
end architecture shift_register_arch;

configuration cfg_shift_register of shift_register is
  for shift_register_arch
  end for;
end cfg_shift_register;


---------- Post added at 17:28 ---------- Previous post was at 16:58 ----------

i should add that i am not allowed to declare any other unit (FF for example)
 

looking at this code, its almost as if you're trying to use recursion to get this working.

I suggest using a single process - create an array of std_logic_vectors that can be the paramaterised shift register:

type shift_reg_t is array(G_SHIFT_REGISTER_SIZE-1 downto 0) of std_logic_vector(G_DATA_WIDTH-1 downto 0);

and then its a simpe case of writing this in a process:

shift_reg <= shift_reg(shift_reg'high-1 downto 0) & input;
output <= shift_reg(shift_reg'high);
 

but how exactly does it take into account the enable and reset?
and i'm not quite sure how the generate works with/parallel to the process..
 

thanks for the example- it's very helpful.
however, i seem to have a problem with the type i declared. i'm probably just doing this wrong, but i'm getting an "illegal target" error.
this is how i wrote it:
t_shift_reg <= t_shift_reg(G_SHIFT_REGISTER_SIZE-1 downto 0) & Data_in;
Data_out_full <= t_shift_reg;

i tried also:
Data_out <= t_shift_reg(t_shift_reg'high)

i'm sorry for being a nag, i just don't understand this... and i can't find a proper guide or reference for this.
 

you need to declare the type, and then declare a signal of that type. You cannot use the type directly.

type shift_reg_t is array(G_SHIFT_REGISTER_SIZE-1 downto 0) of std_logic_vector(G_DATA_WIDTH-1 downto 0);
signal shift_reg : shift_reg_t;
 
  • Like
Reactions: nats_

    nats_

    Points: 2
    Helpful Answer Positive Rating
Thank you!!
i feel rather stupid :???:
 

thanks alot for all your help!
i have another small question:
what is the best way to make all outputs zero? (that is Data_out and Data_out_full)
i tried
Code:
for i in G_SHIFT_REGISTER_SIZE-1 downto 0 LOOP
   shift_reg(i) <= '0'; 
   end LOOP;
but it's not right. the problem is that i have an array of vectors and the length of the vectors is changeable, and i am trying to write a bit into a vector which is obviously wrong.. so how would you do it?
i also thought of using "others" but i'm not quite sure exactly how it works...
 

shift_reg <= (others => (others => '0'));
 
  • Like
Reactions: nats_

    nats_

    Points: 2
    Helpful Answer Positive Rating
you need to declare the type, and then declare a signal of that type. You cannot use the type directly.

type shift_reg_t is array(G_SHIFT_REGISTER_SIZE-1 downto 0) of std_logic_vector(G_DATA_WIDTH-1 downto 0);
signal shift_reg : shift_reg_t;

now i have a problem with the output. i cannot assign the new type to my output because they are of different types...

what i don't understand is why this works:
Data_out <= shift_reg(shift_reg'high);

and this doesn't:
Data_out_full <= shift_reg(shift_reg'high downto 0);

the declarations are:
Data_out : out std_logic_vector (G_DATA_WIDTH-1 downto 0);
Data_out_full : out std_logic_vector (G_SHIFT_REGISTER_SIZE*G_DATA_WIDTH-1 downto 0)

so Data_out_full should be able to contain the entire length of shift_reg. what am i missing?
 

shift reg is an array of arrays (an array of std_logic_vectors to be exactly).

so shift_reg(shift_reg'high) returns the highest array.

shift_reg(shift_reg'high downto 0); returns an array of slvs. data_out is only a single bus, not multiple busses.

I dont quit understand what the full signal does, but you probably want to make that an array of arrays too. Having one big long array is just cumbersome
 
  • Like
Reactions: nats_

    nats_

    Points: 2
    Helpful Answer Positive Rating
shift reg is an array of arrays (an array of std_logic_vectors to be exactly).

so shift_reg(shift_reg'high) returns the highest array.

shift_reg(shift_reg'high downto 0); returns an array of slvs. data_out is only a single bus, not multiple busses.

I dont quit understand what the full signal does, but you probably want to make that an array of arrays too. Having one big long array is just cumbersome

basically the full signal is all the output of the registers. so if G_Shift_register_size is 4, than it should include all four outputs (including Data_out).
i got the assignment as a mold, and i'm supposed to change the declaration of those signals. so i have Data_out_full which is an slv G_Shift_register_size*G_data_width, but it is the wrong type to be assigned the contents of shift_reg... unless i do it one by one (vectors)?
 

basically the full signal is all the output of the registers. so if G_Shift_register_size is 4, than it should include all four outputs (including Data_out).
i got the assignment as a mold, and i'm supposed to change the declaration of those signals. so i have Data_out_full which is an slv G_Shift_register_size*G_data_width, but it is the wrong type to be assigned the contents of shift_reg... unless i do it one by one (vectors)?

sorry, it was suppose to say that i am NOT supposed to change the declaration of those signals
 

you could still write a function to map your type into the massive SLV and vice versa.
 

my problem is that i'm not sure how i access the values in the array shift_reg (of type t_shift_reg).
shift_reg is an array of vectors, and i need all those vectors one after the other in the long vector called Data_out_full, the sizes match, but i'm not sure how to do it technically..
 

like I said, create a function to translate one to the other.
Shift reg arrays are accessed shift_reg(n).

so you need to do this loop, that could be put inside a function:

Code:
for i in shift_reg'range loop
  data_out_full((i+1) *G_SHIFT_REGISTER_SIZE downto i*G_SHIFT_REGISTER_SIZE -1) <= shift_reg(i);
end loop;

see why the t_shift_reg is easy to handle than one long array?
 

like I said, create a function to translate one to the other.
Shift reg arrays are accessed shift_reg(n).

so you need to do this loop, that could be put inside a function:

Code:
for i in shift_reg'range loop
  data_out_full((i+1) *G_SHIFT_REGISTER_SIZE downto i*G_SHIFT_REGISTER_SIZE -1) <= shift_reg(i);
end loop;

see why the t_shift_reg is easy to handle than one long array?

great, thanks!
that's actually what i tried, i just didn't do this part properly:
Code:
for i in shift_reg'range loop


---------- Post added at 10:46 ---------- Previous post was at 09:49 ----------

it works now!
thanks again for ALL the help!
 

i have another question (related):
if i have two signals declared in this way:
Code:
type t_combination is array (G_COMBINATION_LENGTH-1 downto 0) of std_logic_vector (G_NUM_IN_WIDTH-1 downto 0);
signal combination,code : t_combination;

and i need to compare the two of them. i tired:
Code:
omparison: for i in combination'range LOOP
        if (combination((i+1)*G_NUM_IN_WIDTH-1 downto i*G_NUM_IN_WIDTH) /= code((i+1)*G_NUM_IN_WIDTH-1 downto i*G_NUM_IN_WIDTH)) then
          compare:=0;
        end if;
      end LOOP comparison;
but it doesn't seem to work...
 

whats wrong with

if combination(i) /= code(i) then

Remember, combination and code are NOT one big std_logic_vector, so you cannot access them as if they were.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top