Translate

Thursday, May 9, 2013

Scrolling text with 7 segment displays



     First of all I'm sorry I haven't been so active in the last months. I've been very busy. This tutorial is done as a request for a reader that asked me a long time ago how to make text scroll (I hope it's still useful to you and sorry for the delay).
   
     Now on to business. In this tutorial we will be making a scrolling text. In my example I will be making the text 01234567 scroll at the interval of 1 second per character.
     This tutorial builds upon my other tutorial about 7 segment displays that you can find:Here. I recommend reading that first because we will use the exact same components with 2 more added.

     The first new component we need is a clock divider that takes the 1 KHz signal from the first divider and makes a 1Hz signal out of it. This is very simple because we follow the same steps as with the other divider: just count the clk transitions and when they reach 999 you make the output '1'. The code is below:

          library IEEE;
          use IEEE.STD_LOGIC_1164.ALL;
          use IEEE.STD_LOGIC_ARITH.ALL;
          use IEEE.STD_LOGIC_UNSIGNED.ALL;

          entity divfreq2 is
              Port ( clk : in STD_LOGIC;
                        reset : in STD_LOGIC;
                        clko : out STD_LOGIC);
          end divfreq2;

          architecture Behavioral of divfreq2 is

          begin

             process(clk)
                variable cnt:std_logic_vector(9 downto 0);
             begin
                if(clk'event and clk='1') then
                   if(reset='1') then
                      cnt:=(others=>'0');
                      clko<='0';
                   else
                      if(cnt=999) then
                         cnt:=(others=>'0');
                         clko<='1';
                      else
                         cnt:=cnt+1;
                         clko<='0';
                      end if;
                   end if;
                end if;
             end process;

          end Behavioral;



     Now the other circuit we need consists of a simple memory with the 8 characters (we will use an array for this), and a rotate logic so that the elements of the array rotate all the time. 

     An array is a collection of elements that can be referenced by position (exactly like in programming languages). So for example if we have the array a equal to [1,2,3,4,5,6,7,8] we would reference 2 as a(1) or 1 as a(0) and so on. An array can be manipulated as a std_logic_vector as well, meaning that we can reference the first 3 elements like a(7 downto 5) if we declared the array with the highest index on the left or a(0 to 2) if the highest index is in the right.
     When declaring arrays we have to give the type of the elements like std_logic or integer or std_logic_vector etc. For this it is cleaner to make a subtype  and declare the array elements with that subtype. For example here how we create an array of 4 std_logic elements:

          subtype b is std_logic;
          type rl is array(7 downto 0) of b; 

          signal sig : rl;

     Now sig is of type rl which means it's an array of 8 std_logic elements.

     Another thing we will need is to create a constant (a value that never changes). Tis constant will be an array of std_logic_vector elements and represents the characters to display (the memory part of the circuit). You can read about constants and other VHDL elements in one of my posts: Basic VHDL elements.
   
     Now all that remains is to see how to rotate the values continuously. Let's take the array: 1,2,3,4,5,6,7,0. In order to rotate it we have to take each time the first element and place it behind the last one. This way we obtain a right rotate that will not alter the array contents (just the order). For a left rotate you have to take the last element (0) and place it in front of the first one (1).
     Here how the array will look after 3 rotations:
     Original: 1 2 3 4 5 6 7 0
     First rotation: 2 3 4 5 6 7 0 1
     Second rotation: 3 4 5 6 7 0 1 2
    Third rotation: 4 5 6 7 0 1 2 3
    And so on.

    The register will have 4 outputs that go to the multiplexer (keep the signals d0,d1,d2,d3 and link the multiplexer with this register with them) like you will see in the diagram.
     Here is the code for the circuit:

          library IEEE;
          use IEEE.STD_LOGIC_1164.ALL;
          use IEEE.STD_LOGIC_ARITH.ALL;
          use IEEE.STD_LOGIC_UNSIGNED.ALL;

          entity letterreg is
             Port ( clk : in STD_LOGIC;
                       reset : in STD_LOGIC;
                       r0 : out STD_LOGIC_VECTOR (3 downto 0);
                       r1 : out STD_LOGIC_VECTOR (3 downto 0);
                       r2 : out STD_LOGIC_VECTOR (3 downto 0);
                       r3 : out STD_LOGIC_VECTOR (3 downto 0));
          end letterreg;

          architecture Behavioral of letterreg is

              subtype b4 is std_logic_vector(3 downto 0);
              type rl is array(7 downto 0) of b4;
              constant r:rl:=(x"1",x"2",x"3",x"4",x"5",x"6",x"7",x"0");
              signal rsig:rl:=r;

          begin

             process(clk)
             begin
                if(clk'event and clk='1') then
                   if(reset='1') then
                      rsig<=r;
                   else
                      rsig<=rsig(6 downto 0)&rsig(7);
                   end if;
                end if;
             end process;

             r0<=rsig(4);
             r1<=rsig(5);
             r2<=rsig(6);
             r3<=rsig(7);

          end Behavioral;


     I will not be giving the code for the main circuit because it should be easy to make. Or if you want you can make a schematic project.
     The diagram for the project:
   


     Here is a video of the project in action:
   


     For questions or suggestions please email me at: fpgatutorials@gmail.com
     Thank you for reading

7 comments:

  1. it would be nice if you post the whole code :D
    i'm a beginner and i don't understand everything you post on this project, but maybe if i see the entire code, i can figure out.
    anyway, i have to do a bigger project, with 4 ways of displaying a text, so this is kinda helpful. :)

    ReplyDelete
    Replies
    1. Hi. I am not at home right now and I don't know if I still have the project on my PC.
      I will check

      Delete
    2. Buna! Ai putea te rog sa pui codul intreg? Sunt incepator si nu ma prea descurc. Multumesc!

      Delete
  2. i can't figure out, where does the information come from for the first divider (div)?

    ReplyDelete
    Replies
    1. the info on clock...

      Delete
    2. hi. The div circuit get the input from the clock of the FPGA board.
      this has to be mapped in the .ucf file (constraints file)
      by the way I am romanian so you can send mails in romanian if you want

      Delete
  3. Sir will U plz help me displaying msg "welcome home".

    ReplyDelete