Fully-Working Seven Segments
All Eight Digits
Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.
Recall the seven segment display from last week:
We previously used the eight digits (i.e. one of the eight number displays on the board) on the seven-segment display grouped into two identical sets of four. This is a product of how the LEDs (each little line on each digit that lights up red) are connected. We are only able to control:
- Which digits are enabled at a given time, via the anode pins (
ss0_an[3:0]
andss1_an[3:0]
). Driving an anode high disables a given digit, driving it low enables it. (note this is backwards from normal since there is a PNP driving transistor controlling the anode.) - Which LEDs are enabled on all of the digits at a given time, via the cathode pins which control the "0" through "6" segments of the four digits in each LED bank (pins
ss0_c[6:0]
andss1_c[6:0]
are used for banks 0 and 1, respectively). Driving a cathode high would disable a given segment, driving it low enables.
In week one, we labeled the segment cathodes "A" through "G". You can also just label them with numbers, which we'll do here. Same pattern: A=0, 1=B, etc...
Across each bank of four digits, the "0/A" segments of each are tied together for example, same with "1/B", etc... Therefore we are never able to apply a signal to a specific "1/B" segment on any digit. However, since an LED only glows if the anode and cathode are the correct values, by setting this global "1/B" signal to a value we want and then selecting which digits to activate by using certain an
pins, we can at least control which "1/B" pins on particular digits actually light up. The same logic applies for the remaining cathode pins/segments as well like "0/A", "2/C", etc...
Still, while we can turn off particular digits by varying which values of an
are on and off, there is no way using only combinational logic that we could ever show two separate hex symbols on two separate digits. If I needed to show the numbers 0000_1986
, many of these digits are using different combinations of segments and there'd be no way to do this with combinational only logic.
The question that should be jumping out to you is how do we make the different segments say different things at the same time if they're all tied together in this way? The answer is we don't. Or we sorta do, but it is complicated, and relies on the same inadequacies in human vision that we used for PWM control of the RGB LEDs last week. What we can do with our LEDs is light up each of the eight digits with the appropriate pattern for its digit in sequence, while keeping the others off. If we do this fast enough (keeping each digit lit for something like ~1 ms) and repeatedly for each digit, we can make it look like all eight digits are illuminated to our inferior human eyes.
This should seem possible to you. We have access to the anodes (which "activate" a given digit) and we have a system which can make decisions 100 million times per second, about 5 orders of magnitude faster than the 1 ms requirement.
We put together a nice-ish cartoon to show this concept a little bit more clearly:
This may seem like a lot of work just to make a display. Why not just independently control each cathode/segment pin, for example, instead of having all of them share a common control pin? Well the device isn't built that way. And there's a good reason for it. As it turns out, controlling the display by "strobing" each segment drastically cuts down on the number of pins. If we did it the brute-force way, you'd have eight pins per seven-segment display (one common anode, and seven cathodes), times eight segments, that'd be 64 pins needed. No thank you. Doing it this way requires only 15 pins. Pins equate to circuit board and chip real estate and this usually equates to money. As Method Man tells us, Cash Rules Everything Around Me(Us), so strobing LEDs is beneficial.
Let's now build a module called seven_segment_controller
which will be responsible for controlling all eight digits of the seven-segment displays. To make this module as functional as possible (for later usage) it will be responsible for displaying hex on all 8 digits, meaning it can represent 32 bits of information (4 bits per hex symbol) even though we're only using it for 16 in counting button pushes at first (in part 3 of lab we will use all 32 bits!). Consequently, this module should have three inputs:
val_in[31:0]
: A 32 bit input which will get rendered on the display (in hexadecimal)clk_in
: An external system clock for driving the synchronous logic in the modulerst_in
: A reset control in case you'd like to make your module resettable
Additionally, the module will have two sets of outputs:
cat_out[6:0]
: Pins intended to drive the cathode pins in our systeman_out[7:0]
: Pins for selecting/deselecting the individual segments via their anodes (note, again, that driving high an anode disables a given digit)
For the initial deployment, we're counting button pushes. btn_count
is only 16 bits, but the input to the seven segment module is 32 bits. As a result, the upper 16 bits of val_in
will be default 0 and you'll only be able to control the lower four hex digits for this first demo; that's ok. If you really want to push the button more than 65,536 times that's...I mean that's great, but I'm sure there's better things you could do with your time.
We're going to provide an almost-complete version of seven_segment_controller
below. Study this code and get it working. It does not need much more to work like we just described...perhaps ten lines max. The missing piece is effectively to route the appropriate seven-segment pattern to led_out
given the current digit being activated! (See the sequential image above and try to match what it has for values with the code below!).
This module is a very basic form of state machine, which we'll be covering in upcoming lectures/labs! Note that it uses an instance of bto7s
from week 1 so you should bring a copy of that into your project as well (you can either put it in a separate file or include it below in the same file. The choice is yours.)! Other than wiring everything together, this module should just work! When ready, make sure to uncomment the instance of seven_segment_controller
in your top_level
file.
`default_nettype none
module seven_segment_controller #(parameter COUNT_PERIOD = 100000)
(input wire clk_in,
input wire rst_in,
input wire [31:0] val_in,
output logic[6:0] cat_out,
output logic[7:0] an_out
);
logic [7:0] segment_state;
logic [31:0] segment_counter;
logic [3:0] sel_values;
logic [6:0] led_out;
//TODO: wire up sel_values (-> x_in) with your input, val_in
//Note that x_in is a 4 bit input, and val_in is 32 bits wide
//Adjust accordingly, based on what you know re. which digits
//are displayed when...
bto7s mbto7s (.x_in(sel_values), .s_out(led_out));
assign cat_out = ~led_out; //<--note this inversion is needed
assign an_out = ~segment_state; //note this inversion is needed
always_ff @(posedge clk_in)begin
if (rst_in)begin
segment_state <= 8'b0000_0001;
segment_counter <= 32'b0;
end else begin
if (segment_counter == COUNT_PERIOD) begin
segment_counter <= 32'd0;
segment_state <= {segment_state[6:0],segment_state[7]};
end else begin
segment_counter <= segment_counter +1;
end
end
end
endmodule // seven_segment_controller
/* TODO: drop your bto7s module from lab 1 here! */
module bto7s(input wire [3:0] x_in,output logic [6:0] s_out);
endmodule // bto7s
`default_nettype wire
Notice the reset signal in seven_segment_controller
, rst_in
. It is almost always a good idea to give your sequential circuits a reset signal both for regular operation but also for debugging since it can give you the ability to get your circuit back to a known starting state.
For your own local debugging, we've provided a testbench here: test_ssc.py. You should use this to help develop this module. Before posting on piazza about why your code isn't passing the checker, you should make sure to run your simulations locally and study the waveforms.
When the above code is working, update seven_segment_controller.sv
. Make sure to uncomment the instantiation of the seven_segment_module
in the top_level
file and delete any unneeded lines. Build, and upload. Hopefully you're getting a video like below! If so, get the checkoff!
When you have assembled all these pieces, show to a staff member for the second lab checkoff. Note, because it a subset of this checkoff, you can get Checkoff 1 by demonstrating Checkoff 2, but make sure to add yourself to the queue for each.