VHDL – Shift Register

My latest hobby is to learn VHDL and apply to the Mimas V2 FPGA board.  As with any language, reading about the language is all well and good, but attempting a real application is where the rubber hits the road.  I read through several tutorials and some introduction material to familiarize myself with some of the syntax.  I copied some code from example articles and observed how the code worked in simulation mode.  Then I finally decided to try and build a circuit without the code from a tutorial.  Keeping it somewhat simple, I chose to implement a shift register.  My goal was to create a 4-bit shift register that had one input that I could feed a “1” or a “0” per clock cycle.  I also wanted to see all 4 outputs to observe the data bits shifting down the line.  Here’s the circuit:

My first attempt was to just shift the outputs as though they are storage locations.  That caused an error: Cannot read from ‘out’ object output ; use ‘buffer’ or ‘inout’  I discovered that I needed some sort of storage inside my object (the flip-flops that represent my last state).  So I set up a “signal”:

signal dflipflops: STD_LOGIC_VECTOR(3 downto 0):="0000";

You can give your signal any name, I just called it dflipflops because that’s what popped into my head.  As you can see, the data in the signal can be pre-set to some value (in quotes because it’s a vector).

Next, I coded the reset.  I didn’t really need a reset for the simulation since I set the dflipflops to all zeros when the object is initialized.  However, if I decided to use this as a real circuit, I’d have to have a way to reset this at any time.  So I coded my reset as simple as possible:

if (reset = '1') then
    dflipflops <= "0000";
else
    -- shift logic goes here
end if;

Next, I hard-coded the logic of shifting bits (this is just the inner logic):

if (clock='1' and clock'event) then    
    dflipflops(3) <= dflipflops(2);
    dflipflops(2) <= dflipflops(1);
    dflipflops(1) <= dflipflops(0);
    dflipflops(0) <= datain;
end if;

I did this because I wanted to see if the simulation worked, and it didn’t.  I ended up with unknown outputs:

Yup, forgot to translate my signal back out to the outputs:

output(0) <= dflipflops(0);
output(1) <= dflipflops(1);
output(2) <= dflipflops(2);
output(3) <= dflipflops(3);

That worked:

Next, I converted to “for” loops and here’s the final code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- 4-bit shift register
entity shiftregister is port (
datain,clock,reset: in STD_LOGIC;
output: out STD_LOGIC_VECTOR(3 DOWNTO 0)
);
end shiftregister;

architecture Behavioral of shiftregister is
    
    signal dflipflops: STD_LOGIC_VECTOR(3 downto 0):="0000";
    
begin
    process (datain,clock,reset)
    begin
        if (reset = '1') then
            dflipflops <= "0000";
        else
            if (clock='1' and clock'event) then
                for i in 2 downto 0 loop
                    dflipflops(i+1) <= dflipflops(i);
                end loop;
                dflipflops(0) <= datain;
            end if;
        end if;
        
        for k in 3 downto 0 loop
            output(k) <= dflipflops(k);
        end loop;
        
    end process;
end Behavioral;

The test bench code is here:

ENTITY shiftregistertest IS
END shiftregistertest;
 
ARCHITECTURE behavior OF shiftregistertest IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT shiftregister
    PORT(
         datain : IN  std_logic;
         clock : IN  std_logic;
            reset : IN std_logic;
         output : OUT  std_logic_vector(3 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal datain : std_logic := '0';
   signal clock : std_logic := '0';
   signal reset : std_logic := '1';

     --Outputs
   signal output : std_logic_vector(3 downto 0);

   -- Clock period definitions
   constant clock_period : time := 10 ns;
 
BEGIN
 
   -- Instantiate the Unit Under Test (UUT)
   uut: shiftregister PORT MAP (
          datain => datain,
          clock => clock,
             reset => reset,
          output => output
        );

   -- Clock process definitions
   clock_process :process
   begin
        clock <= '0';
        wait for clock_period/2;
        clock <= '1';
        wait for clock_period/2;
   end process;
 

   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for 100 ns;    

      reset <= '0';
        
      wait for clock_period*6;

      -- test 1
      datain <= '1';
      wait for clock_period;
        
      datain <= '0';
      wait for clock_period*6;
      
      -- test 2
      datain <= '1';
      wait for clock_period*2;
                
      datain <= '0';
      wait for clock_period*6;

      wait;
   end process;

END;

For the test bench I first defaulted the reset to a “1” to force a reset at the beginning.  Then I set the reset back to “0” before testing data inputs.  The first test (test 1) feeds a “1” into the datain and then shifts it one clock cycle, then sets the datain back to “0”.  Then I shift 6 times to make the “1” shift all the way out of the shift register.  The next test (test 2), I set the datain to a “1” and shifted it in for two clock cycles, causing two “1”s to be inputted into the shift register.  Then I set datain back to “0” and shifted for 6 clock cycles to watch the two bits shift all the way through the shift register.  Here’s the simulation output:

The first test starts at 170ns and ends around 210ns.  The second test starts at 240ns and ends at 290ns.

One thing I noticed about the editor is that you must select the test source file before double-clicking on “Simulate Behavioral Model”:

Otherwise, you’ll get a result like this:

You also need to close the ISim window before you can run another simulation otherwise, you’ll get an error like:

ERROR:Simulator:904 – Unable to remove previous simulation file isim/shiftregistertest_isim_beh.exe.sim/shiftregistertest_isim_beh.exe. Please check if you have another instance of this simulation running on your system, terminate it and then recompile your design. System Error Message: boost::filesystem::remove: Access is denied: “isim\shiftregistertest_isim_beh.exe.sim\shiftregistertest_isim_beh.exe”ERROR:Simulator:861 – Failed to link the design

Once this error occurs, you’ll need to close the ISim window, then you will need to right-click on the “Simluate Behavioral Model” and select “rerun all”.  Double-clicking just gives this error:

INFO:ProjectMgmt – The selected process was not run because a prior process failed.

One other thing I find annoying about the editor is that there is no file name change capability.  I’ve attempted to change the name of a file and ended up with a mess.  There is a lot of smart linking that goes on between the project and the files that belong to it.  My quick fix is to create a new file with the new name and scrape the code from the old source and paste into the new source.  Then I delete the old file.  It’s dumb and dirty, but it’s also pretty quick.

Other than the few quirks that I’ve worked around, I am happy that the editor is similar to Visual Studio in commands and syntax highlighting.

 

Leave a Reply