Skip to main content

Scrolling or Moving Text Using 7 Segment LED's in Verilog | FPGA

This one is going to be a quick easy project. The objective here is to get use the 7-segment LED display on the board to display a scrolling text. it should be slow enough so that it can be easily read.

I have made the delay between each word shift to be 1 second. This is long enough to read the text comfortably without missing anything. I have explained in my previous post how to create an accurate delay using verilog, you can read about it there: Create accurate delay in Verilog. Now since I need a 1 second delay here the counter monitoring this count must count to 50,000,000. And the register needed to hold this count must be 29 bits wide.

Using this method you can scroll and display anything. Here I have chosen to display the text "Hello There" to scroll across the LED's and appear to be continuous without any stops. The concept is pretty simple. I create a separate counter that increments every time a count of 50,000,000 is reached. This counter will count till 8, display the entire text, and then reset back to 0 so that the text can be scrolled again. For every count increment it will match it with a case statement. This case will instruct the display for that second.

Now since 7 segment LED's are being used here you must have a proper understanding of them before trying to read and understand the code. I have detailed the topic in detail here: 7 Segment LED Multiplexing in Verilog. Be sure to read and understand it.

So instead of displaying numbers the plan is to display letters on the LED's. This can be achieved by changing the case statement to our requirements.

As usual the code is commented in detail and should be self explanatory even without the above rant. A video demonstration has been added at the end.

module scrolling_name(
    input clock,
    input reset,
    output a,
    output b,
    output c,
    output d,
    output e,
    output f,
    output g,
    output dp,
    output [3:0] an
    );

reg [28:0] ticker; //to hold a count of 50M
wire click;
reg [3:0] fourth, third, second, first; // registers to hold the LED values

always @ (posedge clock or posedge reset) //always block for the ticker
begin
 if(reset)
  ticker <= 0;
 else if(ticker == 50000000) //reset after 1 second
  ticker <= 0;
 else
  ticker <= ticker + 1;
end

reg [3:0] clickcount; //register to hold the count upto 9. That is why a 4 bit register is used. 3 bit would not have been enough.

assign click = ((ticker == 50000000)?1'b1:1'b0); //click every second

always @ (posedge click or posedge reset)
begin
 if(reset)
  clickcount <= 0;
 else if(clickcount == 8)
   clickcount <= 0;
  else 
  clickcount <= clickcount + 1;

end

always @ (*) //always block that will scroll or move the text. Accomplished with case
begin
    case(clickcount)
    0:
    begin
     fourth = 4; //H
     third = 3; //E
     second = 7; //L
     first = 7; //L
    end
    
    1:
    begin
     fourth = 3; //E
     third = 7; //L
     second = 7; //L
     first = 0; //O
    end
    
    2:
    begin
     fourth = 7; //L
     third = 7; //L
     second = 0; //O
     first = 2; //-
    end
    
    3:
    begin
     fourth = 7; //L
     third = 0; //O
     second = 2; //-
     first = 1; //T
    end
    
    4:
    begin
     fourth = 0; //O
     third = 2; //-
     second = 1; //T
     first = 4; //H
    end
    
    5:
    begin
     fourth = 2; //-
     third = 1; //T
     second = 4; //H
     first = 3; //E
    end
    
    6:
    begin
     fourth = 1; //T
     third = 4; //H
     second = 3; //E
     first = 8; //R
    end
    
    7:
    begin
     fourth = 4; //H
     third = 3; //E
     second = 8; //R
     first = 3; //E
    end
    
    8:
    begin
     fourth = 3; //E
     third = 8; //R
     second = 3; //E
     first = 2; //blank
    end
  endcase
  
end

//see my other post on explanation of LED multiplexing.

localparam N = 18;

reg [N-1:0]count;

always @ (posedge clock or posedge reset)
 begin
  if (reset)
   count <= 0;
  else
   count <= count + 1;
 end

reg [6:0]sseg;
reg [3:0]an_temp;

always @ (*)
 begin
  case(count[N-1:N-2])
   
   2'b00 : 
    begin
     sseg = first;
     an_temp = 4'b1110;
    end
   
   2'b01:
    begin
     sseg = second;
     an_temp = 4'b1101;
    end
   
   2'b10:
    begin
     sseg = third;
     an_temp = 4'b1011;
    end
    
   2'b11:
    begin
     sseg = fourth;
     an_temp = 4'b0111;
    end
  endcase
 end
assign an = an_temp;

reg [6:0] sseg_temp; 
always @ (*)
 begin
  case(sseg)
   4 : sseg_temp = 7'b0001001; //to display H
   3 : sseg_temp = 7'b0000110; //to display E
   7 : sseg_temp = 7'b1000111; //to display L
   0 : sseg_temp = 7'b1000000; //to display O
   1 : sseg_temp = 7'b0000111; //to display T
   8 : sseg_temp = 7'b0001000; //to display R
   
   default : sseg_temp = 7'b1111111; //blank
  endcase
 end
assign {g, f, e, d, c, b, a} = sseg_temp; 
assign dp = 1'b1;

endmodule

Comments

  1. i want ucf code for the above verilog code

    ReplyDelete
    Replies
    1. Hi,

      the .ucf file for the BASYS2 board can be found here:

      http://simplefpga.blogspot.co.uk/2012/06/user-constraint-file-ucf-for-basys2.html

      Do note that if your board is not BASYS2 this will not work.

      Delete
  2. Nice, this helped a lot! Hope you don't mind I posted a modified version of your code to stack overflow - http://stackoverflow.com/questions/15194206/seven-segment-multiplexing-on-basys2/15301085#15301085

    ReplyDelete
    Replies
    1. Thats alright, Nathan. I really like what you've done thanks for letting me know. I'm happy this helped you out :)

      Delete
  3. Nice, very useful content you got there, mate. I went through all of it but I am doing on a altera cyclone board. But we can't find the output pins configured would be mind providing that. I tried only on 7 segment display works and isn't shifting.

    ReplyDelete
    Replies
    1. I use the BASYS2 board, the ucf file I have for my board wont work with your board. You have to find the .UCF file for your ALTERA board from either the manufacturers website or from Google.

      Delete
    2. Can you at least tell which one is the output register so I can assign the pin accordingly. Cheers

      Delete
    3. Rahat, the output register is the "sseg_temp" in the code. But in terms of hardware this register is connected to the seven individual LED's of the seven segment display via the line: "assign {g, f, e, d, c, b, a} = sseg_temp; "

      So you need to assign {a, b ,c, d, e, f, g} in your ucf file

      Delete
  4. I tried going through the whole web in three weeks it seems there aren't any documents on how to scroll the seven segment display on Altera cyclone iv board. I tried going through your code and try to replicate it but I can't make the seven segment move for one to another.

    ReplyDelete
    Replies
    1. Are you sure your ucf file is accurate?

      Delete
    2. No worries I found a solution for the scrolling text for later cyclone DE115 board. I would be happy if you can upload it on your blogspot.

      Delete
    3. Thats great. No thanks, all my posts are related to the BASYS2. But I'm sure if someone needs the code they would know how to contact you. :)

      Delete
  5. Very well written and informative article, thank you :-)

    Moving Display Board

    ReplyDelete
  6. Found it very helpful indeed! However, if I want to scroll or shift my text both ways (from left to right and vice versa) what modification will be required in your above mentioned code?

    ReplyDelete
  7. can you please help me assigning the pins?

    ReplyDelete
    Replies
    1. Hi, Please refer to this post for pin assignment. You will need the .ucf file for your board. http://simplefpga.blogspot.co.uk/2012/06/user-constraint-file-ucf-for-basys2.html

      Delete
  8. sir i need your help urgently please reply me. What is dp output?

    ReplyDelete
    Replies
    1. dp is the output for decimal point on the 7 segment display. Please refer to this post for a detailed description: http://simplefpga.blogspot.co.uk/2012/07/seven-segment-led-multiplexing-circuit.html

      Delete
    2. Thanks for replying. Can you tell me that what is 5M i mean to say that either it is the frequency of clock that we have to store in a register or either it is the time in Nano Seconds. Please explain this thing.

      Delete
  9. will your code work in basys 3?

    ReplyDelete
  10. How can I modify it so that it only displayed 1 2 3 4

    ReplyDelete

Post a Comment

Popular posts from this blog

To Code a Stopwatch in Verilog

The stopwatch coded here will be able to keep time till 10 minutes. It will be a 4 digit stopwatch counting from 0:00:0 till 9:59:9. The right most digit will be incremented every 0.1 second, when it reaches 9 it will increment the middle two digits, which represent the second count. When it reaches 59 seconds it will increment the right most minute display. The stopwatch will be in the format M:SS:D. How to Create an Accurate Delay in Verilog: To make the stop watch an accurate device we need to be able to produce an accurate 0.1 second delay. I have already explained how to do this before in my decimal counter in verilog post. But since it is of great importance to the design will be explained in more detail here. Since we know that the BASYS2 (the one I am using, yours may be different) has a 50 MHz clock which means that the clock cycle is repeated 50M times in one second. So to create a 0.1 second delay we multiply the clock with the required time: 50MHz * 0.1 sec =

Seven Segment LED Multiplexing Circuit in Verilog

The seven segment LED circuit uses seven different and individual LED's to display a hexadecimal symbol. It has 7 wires to control the individual LED's one wire to control the decimal point and one enable wire. The demo board I am using here consists of four such 7-segment LED's(As do any other demo board). To reduce the number of wires a multiplexing circuit is used to control the display. Using the multiplexing circuit the number of wires required to light up all 4 displays are reduced from 32 to 12 (8 data bits and 4 enable bits). All bits here are active low, such that to enable them a '0' is required. For example the figure below shows how to display a 3 on the seven segment. The multiplexing circuit can take 4 inputs and have only one output. But the inputs should be displayed on the output fast enough to fool the viewer into thinking all outputs are enabled individually and simultaneously. This is achieved by having an enable signal that changes so fast t

Random Number Generator in Verilog | FPGA

In verilog a random number can be generated by using the $random keyword but that works only for simulation purposes and cannot be implemented. So when we need a random number for implementation i.e. in hardware it can be achieved using an LFSR (Liner Feedback Shift Register). An LFSR is simply a shift register with some of its bits (known as taps) XOR'd with themselves to create a feedback term. When implementing an LFSR it's width and it's repeatability must be kept under consideration .An N-bit LFSR will be able to generate (2**N) - 1 random bits before it starts repeating. For example a 30 bit LFSR will have 1073741823 random states before repeating, so for most practical purposes this can be considered true random. In an LFSR the MSB will always be the feedback point also the main thing to take care of while coding an LFSR is to know which bits are the taps (to be selected for XOR ). This is confusing as the taps are different for different size registers. For e