Hello readers, welcome back.
So far we have discussed a lot about verilog and FPGA Introduction. So let’s implement something. The video tutorial for this has been posted on youtube. You can watch that as well. I have written all the verilog codes in this blog so it will help you.
In this blog we will see how to make a BCD controller. We need a BCD controller to control all the 7-segment displays of the FPGA individually.
7-segment display Total 8 digital signals are required to form a character (or number)
Most FPGAs have multiple 7-segment displays. I have used a FPGA from Spartan 6 family and below is the image for that. All the four 7-seven segment displays share common control wires for signals {A,B,C,D,E,F,G,DP}, so if we switch on all of them then all of them will show the same number. We want to display different numbers hence we are designing a system which will help us do that.
The above block diagram shows our approach to implement it. At a particular instant only one of the four 7-segment displays will be active and the rest will be inactive and at the next clock cycle the 2nd one will be active and so on. The frequency for updating will be so fast that we won't be able to notice the switching and it will appear as if it’s glowing continuously.
All the verilog code is available here, I will be explaining about the modules one by one.
Modules function
1. Digit select
This module takes input a system clock and gives a 2-bit vector output sel which is used to determine which digit will be displayed and which anode will be active.
module digit_select(clk,sel);
input clk;
output reg [1:0]sel = 2'b00;
reg [9:0]count = 10'd0;
reg new_clk = 0;
parameter prescaler = 1000; // refresh frequency is 50KHz
always @(posedge clk)
begin
if(count == prescaler)
begin
count <= 0;
new_clk <= ~new_clk;
end
else count <= count + 1;
end
always @(posedge new_clk) sel <= sel + 1;
endmodule
Here we take the input clock and generate a new clock of a bit lower frequency (50 KHz). At every positive edge of the new clock we increment the value of sel. Hence we get a total of 4 different states for sel (i.e. 00,01,10,11).
2. Anode select
This module takes input vector sel and switches on the anode accordingly
module anode_controller(sel,anode);
input [1:0]sel;
output reg [3:0]anode = 4'd0;
always @(sel)
begin
case(sel)
2'd0 : anode = 4'b0001; //right most
2'd1 : anode = 4'b0010;
2'd2 : anode = 4'b0100;
2'd3 : anode = 4'b1000; //left most
endcase
end
endmodule
For 00 the right most anode is active and for 11 left most and so on.
3. Digit control
This module takes input vector sel and all four digits and outputs a single digit that is to be shown at that moment according to sel value. Note both the anode output and digit should be for same 7-segment display.
module digit_control(ones,tens,hundreds,thousands,sel,data);
input [3:0]ones,tens,hundreds,thousands;
input [1:0]sel;
output reg [3:0]data = 4'd0;
always @(sel)
begin
case(sel)
2'b00 : data = ones;
2'b01 : data = tens;
2'b10 : data = hundreds;
2'b11 : data = thousands;
endcase
end
endmodule
4. BCD converter
This module takes input the binary data from the digit control module and outputs the signals for {A,B,C,D,E,F,G,DP} to show proper numbers on the 7-segment display.
module BCD_convertor(data,out);
input [3:0]data;
output reg [7:0]out = 8'd0;
always @(data)
begin
case(data)
4'b0000 : out = 8'b00000011;
4'b0001 : out = 8'b10011111;
4'b0010 : out = 8'b00100101;
4'b0011 : out = 8'b00001101;
4'b0100 : out = 8'b10011001;
4'b0101 : out = 8'b01001001;
4'b0110 : out = 8'b01000001;
4'b0111 : out = 8'b00011111;
4'b1000 : out = 8'b00000001;
4'b1001 : out = 8'b00001001;
default : out = 8'b11111111;
endcase
end
endmodule
- Finally we combine everything in a top module and then we will upload the code to FPGA to see the desired results.
- Before burning the code into FPGA make sure to configure input and output by making a .ucf file.
module top(clk,ones,tens,hundreds,thousands,anode,out);
input [3:0]ones,tens,hundreds,thousands;
input clk;
output [3:0]anode;
output [7:0]out;
wire [1:0]sel;
wire [3:0]data;
digit_select DS(
.clk(clk),
.sel(sel)
);
anode_controller AC(
.sel(sel),
.anode(anode)
);
digit_control DC(
.ones(ones),
.tens(tens),
.hundreds(hundreds),
.thousands(thousands),
.sel(sel),
.data(data)
);
BCD_convertor BCD(
.data(data),
.out(out)
);
endmodule
I hope you enjoyed and learned something from this tutorial. That’s all for today, we will meet again. Until then explore and try to implement your own ideas. Keep learning……!!!
This blog has been submitted by KRSSG, IIT-Kharagpur under the Robocraze Club Outreach Program.
Author: Anubhav Prasad