Search code examples
vhdl

VHDL shift register with enable


I am newbie to VHDL. I am implementing serial in serial out 72 bit shift register using VHDL. When the enable signal is high, I want the shift register to shift 72 times, irrespective of whether enable continues to be high or low. I have written the following code which is working only when the enable is high. Can anyone please help me to shift data once enable is high and then does not depend on enable to shift the data?


library ieee; 
use ieee.std_logic_1164.all; 

entity SR is
  port(clk, din, rst, enable : in std_logic; 
       sr_out : inout std_logic_vector(71 downto 0)); 
end SR; 

architecture behavioral of SR is 
   signal shift_reg: std_logic_vector(71 downto 0); 
begin

process (clk, rst) 
begin 
   if (rst = '0') then
      shift_reg <= (others => '0');
   elsif (clk'event and clk = '1') then
      if enable= '1' then 
         shift_reg(70 downto 0) <= shift_reg(71 downto 1);
         shift_reg(71) <= din;
      end if;
   end if;

end process;
sr_out <= shift_reg;
end behavioral; 

Thanks a lot!


Solution

  • You need a two states machine to do so. Here's a very good idea of how to do it. I'm pretty sure it does what you need or is very close to.

    library ieee; 
    use ieee.std_logic_1164.all; 
    
    entity SR is
       port(
             clk      : in std_logic;
             din      : in std_logic;
             rst      : in std_logic;
             enable   : in std_logic;
             sr_out   : inout std_logic_vector(71 downto 0)
       ); 
    end SR; 
    
    architecture behavioral of SR is 
       signal shift_reg  : std_logic_vector(71 downto 0); 
       signal shift_cnt  : integer range 0 to 72 := 0;
    
       type T_STATE_TYPE is (IDLE, COUNTING);
       signal current_state : T_STATE_TYPE;
    
    begin
    
    p_shift_counter : process(clk,rst)
    begin
    
       if rst = '1' then
          current_state <= IDLE;
          shift_cnt <= 0;
    
       elsif rising_edge(clk) then   
    
          if (current_state = IDLE) then --no enable detected yet
             shift_cnt <= 0;
             if enable = '1' then
                current_state <= COUNTING;
    
             end if;      
    
          elsif (current_state  = COUNTING) then --will stay in that state until it finishes counting
             if (shift_cnt < 72) then
                shift_reg(0) <= din;
                for i in 0 to 71 loop shift_reg(i+1) <= shift_reg(i); end loop; --shifting register
                shift_cnt <= shift_cnt + 1;
             else
                current_state <= IDLE; --finished counting
             end if;
    
          end if;
    
       end if;
    
    end process;
    
    sr_out <= shift_reg;
    
    end behavioral;