Lab #2: Adder/Multipler with Seven Segment Display Driver
In this lab, you will create Adder/Multiplier with Seven Segment Display Driver. The block diagram for the complete system is shown below.
Part I Creation of the Individual HDL Modules
Please refer to pages 15-20 in the Spartan-3 Starter Kit Board User Guide for more information on the Seven-Segment Display (SSD), LEDs, and Switches on the FPGA board
Module 1: SSD Driver Module
The SSD Driver will accept 16-bit data and output the numbers 0-9999 on the Seven Segment Display. Since the 16-bit input data has a range of 0-65535 the SSD driver will also indicate an overflow condition by lighting only the middle display as shown below
The inputs to the SSD driver will be:
Div_clk / System clock divided by from Clock Divider ModuleReset / Reset from button (BTN3) on the FPGA board
Blank / Indicates not to display anything on SSD
SSD_data [15:0] / Input data to be displayed on SSD
The outputs of the SSD driver will be
SSD_out [0:7] / 8-bit data to SSDEnable0 / SSD enable for pin D14
Enable1 / SSD enable for pin G14
Enable2 / SSD enable for pin F14
Enable3 / SSD enable for pin E13
The SSD driver module will use combinational logic and comparators to extract the individual digits from the 16-bit input data.For example, for an input of 3454 decimal, you need to extract (3) for SSD3 (4) for SSD2 (5) for SSD1 and (4) for SSD0 or if the input number is 92 you need to display (BLANK) for SSD3 (BLANK) for SSD2 (9) for SSD1 and (2) for SSD0. On the following page I have included some of the Verilog HDL code for the SSD Driver module. You have the choice of just completing the HDL code or writing your own SSD driver module.
PARTIAL HDL CODE FOR SSD DRIVER
parameter ZERO=8'b00000011;
parameter ONE=8'b10011111;
parameter TWO=8'b00100101;
parameter THREE=8'b00001101;
parameter FOUR=8'b10011001;
parameter FIVE=8'b01001001;
parameter SIX=8'b01000001;
parameter SEVEN=8'b00011111;
parameter EIGHT=8'b00000001;
parameter NINE=8'b00001001;
parameter BLANK=8'b11111111;
parameter OVERFLOW=8'b11111101;
wire [7:0] SSD3;
wire [9:0] SSD2_indicator;
wire [7:0] SSD2;
wire [9:0] SSD1_indicator;
wire [9:0] SSD1;
wire [7:0] SSD0_indicator;
wire [7:0] SSD0;
wire overflw = (data_SSD >=10000);
reg [1:0] anode_enable;
always @ (posedge div_clk)
if (reset)
anode_enable <=0;
else
anode_enable <= anode_enable + 1;
assign SSD_out=(!enable0) ? SSD0
: (!enable1) ? SSD1
: (!enable2) ? SSD2
: (!enable3) ? SSD3
: BLANK;
assign enable0=(anode_enable==0) ? 0 : 1;
assign enable1=(anode_enable==1) ? 0 : 1;
assign enable2=(anode_enable==2) ? 0 : 1;
assign enable3=(anode_enable==3) ? 0 : 1;
assign SSD3=(overflw) ? OVERFLOW
:(blank) ? BLANK
:(data_SSD >=9000) ? NINE
:(data_SSD >=8000) ? EIGHT
:(data_SSD >=7000) ? SEVEN
:(data_SSD >=6000) ? SIX
:(data_SSD >=5000) ? FIVE
:(data_SSD >=4000) ? FOUR
:(data_SSD >=3000) ? THREE
:(data_SSD >=2000) ? TWO
:(data_SSD >=1000) ? ONE
: BLANK;
assign SSD2_indicator=(SSD3==NINE) ? data_SSD-9000
:(SSD3==EIGHT) ? data_SSD-8000
:(SSD3==SEVEN) ? data_SSD-7000
:(SSD3==SIX) ? data_SSD-6000
:(SSD3==FIVE) ? data_SSD-5000
:(SSD3==FOUR) ? data_SSD-4000
:(SSD3==THREE) ? data_SSD-3000
:(SSD3==TWO) ? data_SSD-2000
:(SSD3==ONE) ? data_SSD-1000
: data_SSD[9:0];
assign SSD2=(overflw) ? OVERFLOW
:(blank)? BLANK
:(SSD2_indicator >= 900) ? NINE
:(SSD2_indicator >= 800) ? EIGHT
:(SSD2_indicator >= 700) ? SEVEN
:(SSD2_indicator >= 600) ? SIX
:(SSD2_indicator >= 500) ? FIVE
:(SSD2_indicator >= 400) ? FOUR
:(SSD2_indicator >= 300) ? THREE
:(SSD2_indicator >= 200) ? TWO
:(SSD2_indicator >= 100) ? ONE
:(SSD3==BLANK) ? BLANK
:ZERO;
Now finish the SSD driver module by adding the logic for SSD1 and SSD0
Adder/Multiplier HDL Module
The Adder/Multiplier HDL module will accept 8-bit input data from the slide switches (SW7-SW0) located on the FPGA board. Button (BTN0) on the FPGA board is used to transition the state machine to the next state. The MODE input is used to indicate whether the 2 operands should be added or multiplied together. The adder/multiplier module consists of state machine controller a small data path. The ASM chart for the Adder/Multiplier module can be found on the following page. The input and outputs of the Adder/Multiplier HDL module are shown below.
The Inputs to the Adder/Multiplier module
Clk / 50 MHz system clockReset / Reset from button (BTN3) on the FPGA board
Button_0 / Button (BTN0) used for state transition
Mode / Indicates whether the 2 operands should be adder or multiplied together
Data_in [7:0] / Input data generated from the 8 slide switches (SW7-SW0) on FPGA board
The Outputs of the Adder/Multiplier module
Blank / Indicates that SSD should be ‘BLANK’Data_out [15:0] / Data to SSD module for Decoding
State_indicator [3:0] / The state indicator is a 4-bit wire that is connected to LEDs: LD3-LD0. This will allow you to see what state your state machine is currently at.
ASM Chart for Adder/Multiplier Controller
The adder/multiplier module will transition states whenever one of the buttons on the Spartan 3 board is pushed. As a form of button debounce we can delay for a fewseconds after the button is pushed. If there is not a delay after the button is pressed your state machine will cycle past the next state before you can depress the button.
A counter can be used to allow to you create a delay inside of a state machine
The following code segment shows how to delay 20.97 ms seconds after a button is pushed. The input clock is 50 MHz.
//Verilog HDL example to delay 20.97ms after input button is pressed
parameter S_reset=0;
parameter S_wait_button=1;
parameter S_delay=2;
reg [4:0] state, next_state;
parameter DELAY_REG_SIZE=19;
reg [DELAY_REG_SIZE-1:0] delay_counter;
always @ (posedge clock)
begin
if (reset)
delay_counter <=0;
else begin
if (state==S_delay)
delay_counter <= delay_counter + 1;
end
end
always @ (posedge clk)
if (reset)
state <=0;
else
state <= next_state;
always @(*)
begin
next_state=state; //default value if next_state does not get reassigned in the casestatement
begin //then the state machine will stay in the current state
case(state)
S_reset: next_state=S_wait_button;
S_wait_button: begin
if (button_in)
next_state=S_delay;
end
S_delay: begin
if (delay_counter== 2**DELAY_REG_SIZE-1)
next_state=S_wait_button;
end
default: next_state=S_reset;
endcase
end
end
The Adder/Multiplier module Datapath consists of:
8-bit registers: temp_reg1 and temp_reg2.
16-bit register: temp_reg3
4-bit wire: state_indicator: The state indicator is a 4-bit wire that is connected to LEDs LD3-LD0. This will allow you to see what state your state machine is currently at.
1-bit register: blank. Blank is a control signal to the SSD driver to indicate that nothing should be displayed on the SSD.
26-bit register: delay_counter.
CurrentState DataPath Operation
S_input1 / 8-bit input data from slide switches on FPGA board stored to temp_reg1S_input2 / 8-bit input data from slide switches on FPGA board stored to temp_regi2
S_delay1, S_delay2, S_delay3 / Increment Delay counter by ‘1’
S_delay2 & delay_counter==2**DELAY_REGSIZE -2 / temp_reg1 and temp_reg2 added/multiplied together then stored to temp_reg3
S_delay1, S_delay2, S_delay3 / Blank set to logic ‘1’
All states / Current state displayed on LEDs LD3-LD0
Whenever the state machine is in states Input 1 and Input 2 the 8-bit input data from the switches should be passed through to the SSD. In state S_output the result of the addition or multiplication of the 2 input numbers should be displayed on the SSD. Whenever the state machine is in S_delay1, S_delay2, S_delay3 the BLANK signal should be set to logic ‘1’ so nothing is displayed on the SSD.
CurrentState / SSD displayS_input1, S_input2 / 8 bit input data from the slide switches on the FPGA board
S_output / the result of the addition or multiplication of the 2 input numbers
S_delay1, S_delay2, S_delay3 / ‘Blank’
A hardware mux can be used to select the output data based on the current state.
assign data_out=(state==S_state1) ? {8’b0,data_in}
:(state==S_state3) ? temp_output
:16’b0;
Since the input to the SSD driver is 16-bits to display the 8-bit input data you should concatenate 8 zeros to the 8 bit input data similar to the example above.
Mode Select Module
The mode select module is a FSM that will be used to synchronously change the mode of the Adder/Multiplier Module. Whenever Mode is set to logic ‘1’ the adder multiplier will multiply the two operands and whenever the mode is set to logic’0’ the adder/multiplier module will add the two operands. The ASM chart for the Mode Select Module is shown below.
The Inputs to the Mode Select module
Clk / 50 MHz system clockReset / Reset from button BTN3 on the FPGA board
Button_1 (BNT2 on FPGA board) / Button used to toggle Mode
The Outputs of the Mode Select module
Mode / Indicates whether the 2 operands should be adder or multiplier togetherMode Indicator / Use LED LD7 on the FPGA board
The Mode Select module Datapath consists of:
1-bit register: mode.
26-bit register: delay_counter
CurrentState DataPath Operation
S_toggle_mode / Mode toggledS_delay / Delay Counter incremented by 1
Whenever the state machine is in stateS_toggle_mode the mode register should be toggled. After the mode is toggled the state machine will delay for clock cycles or 1.34 seconds before the mode can be toggled again.
Clock Divider Module
The clock divider module will be used to divide the clock to the SSD driver module. The SSD display will not appear properly if the input clock frequency is too fast or too slow. A counter can be used to easily divide the SSD input clock by a power of 2. The register size is the dividing factor.
For example the following code segment divides the clock by or 8;
assign clk_div_out=clk_div_temp[2];
reg [2:0] clk_div_temp;//3 bit register
always @ (posedge clk)
begin
if (reset)
clk_div_temp <=0;
else
clk_div_temp <= clk_div_temp + 1;
end
The clock divider for the SSD driver module should divide the 50MHzclock from pin T9
by 65536 or to produce a input clock with a frequency of 762.94 Hz.
The Inputs to the Clock Divider module
Clk / 50 MHz system clockReset / Reset from button BTN3 on the FPGA board
The Output of the Clock Divider module
Clk_div_out / 762.94 Hz clockPART II
Create Top/Wrapper Module
A top/wrapper module needs to be created to connect all of the HDL modules together. Below is the top/wrapper module I used for my design.
module ssd_top (
input clk,
input reset,
input [7:0] data_in,
input button0,
input button1,
output [0:7] SSD_out,
output [3:0] state_indicator,
output enable0,
output enable1,
output enable2,
output enable3,
output mode_indicator
);
wire div_clk;
wire blank;
wire [15:0] data_out;
wire mode;
mode_select MS(
.clk(clk),
.button1(button1),
.reset(reset),
.mode(mode),
.mode_indicator(mode_indicator)
);
Adder ADD(
.clk(clk),
.reset(reset),
.button0(button0),
.mode(mode),
.data_in(data_in),
.blank(blank),
.data_out(data_out),
.state_indicator(state_indicator)
);
SSD_driver SSD(
.div_clk(div_clk),
.reset(reset),
.blank(blank),
.data_SSD(data_out),
.SSD_out(SSD_out),
.enable0(enable0),
.enable1(enable1),
.enable2(enable2),
.enable3(enable3)
);
clock_div CKD(
.clk(clk),
.reset(reset),
.div_clk(div_clk)
);
endmodule
PART III
Synthesize and Implement the Design
Now, create a UCF file for the project similar to the one shown below. Once the UCF file is created, synthesize, implement, and download your design to the Spartan-3 board.
NET "clk" LOC = "T9" ;
NET "reset" LOC = "L14" ;
NET "button0" LOC = "M13" ;
NET "button1" LOC = "L13" ;
NET "data_in[0]" LOC = "F12" ;
NET "data_in[1]" LOC = "G12" ;
NET "data_in[2]" LOC = "H14" ;
NET "data_in[3]" LOC = "H13" ;
NET "data_in[4]" LOC = "J14" ;
NET "data_in[5]" LOC = "J13" ;
NET "data_in[6]" LOC = "K14" ;
NET "data_in[7]" LOC = "K13" ;
NET "enable0" LOC = "D14" ;
NET "enable1" LOC = "G14" ;
NET "enable2" LOC = "F14" ;
NET "enable3" LOC = "E13" ;
NET "SSD_out[0]" LOC = "E14" ;
NET "SSD_out[1]" LOC = "G13" ;
NET "SSD_out[2]" LOC = "N15" ;
NET "SSD_out[3]" LOC = "P15" ;
NET "SSD_out[4]" LOC = "R16" ;
NET "SSD_out[5]" LOC = "F13" ;
NET "SSD_out[6]" LOC = "N16" ;
NET "SSD_out[7]" LOC = "P16" ;
NET "state_indicator[0]" LOC = "K12" ;
NET "state_indicator[1]" LOC = "P14" ;
NET "state_indicator[2]" LOC = "L12" ;
NET "state_indicator[3]" LOC = "N14" ;
NET "mode_indicator" LOC = "P11" ;
Once you have downloaded your project and confirmed that it is working as expected:
- Demonstrate the operation of your 8-bit adder/multiplier with the decimal, 7-segment LED displays on the Spartan-3 board to the lab instructor.
- Obtain printouts of all of your synthesis report and the UCF file for your lab report.