After finishing the beginner’s guide for the Mimas V2 Development Board, I decided to try my hand at a circuit that I previously built with the GAL16V8 chip. I already had the PDS file for the BCD to Hexadecimal LED display, so I decided to try that. First, I needed to figure out what I could use for inputs. The Mimas board has an 8-position DIP switch. I used switch 1 through 4 for the BCD input. I also used push button switch number 1 for the lamp test input. If you go to this website, you can find all the schematics that show inputs and outputs. Here are the inputs:
According to the diagram above, I chose to use M18 for the lamp test and dip switches F17, F18, E16, E18 for my BCD inputs. All switches are active low, so I needed pull-up resistors and had to reverse the input logic to the module (a zero is inputted when the switch is ON).
Next, the outputs. There are three 7-segment displays, so I chose display 1. To enable the display, I applied a zero to the enable transistor. Also, I had to disable the other two displays by applying a “1”. Here’s the schematic:
So B3 must be set to “0” and A2 and B2 must be set to a “1”. Then segment A is A3, segment B is B4, segment C is A4, etc. The UCF file for the program will look like this:
# User Constraint File for BCD to 7-Segment Hex Display implementation on Mimas V2 NET "A" LOC = A3; NET "B" LOC = B4; NET "C" LOC = A4; NET "D" LOC = C4; NET "E" LOC = C5; NET "F" LOC = D6; NET "G" LOC = C6; NET "EN1" LOC = B3; NET "EN2" LOC = A2; NET "EN3" LOC = B2; # Switches. # Internal pull-ups need to be enabled since # there is no pull-up resistor available on board NET "D0" PULLUP; NET "D1" PULLUP; NET "D2" PULLUP; NET "D3" PULLUP; NET "LT" PULLUP; NET "D0" LOC = F17; NET "D1" LOC = F18; NET "D2" LOC = E16; NET "D3" LOC = E18; NET "LT" LOC = M18;
Now, it’s time to create the logic. I discovered the AND, OR, NOR, etc. circuits from this tutorial: Verilog Tutorial. So I created OR/AND combinations for each segment like this:
and (a1, D0, D2); and (a2, D0, !D3); and (a3, !D1, !D2); and (a4, !D1, D2, D3); and (a5, !D0, !D2, D3); and (a6, D1, D2, !D3); nor (A, a1, a2, a3, a4, a5, a6, !LT);
This came from the following formula used in my GAL16V8 circuit:
/A = /RBO*/D0*/D2 + /RBO*/D0*D3 + /RBO*D1*D2 + /RBO*D1*/D2*/D3 + /RBO*D0*D2*/D3 + /RBO*/D1*/D2*D3 + LT
I did not implement the RBO (Ripple Blanking Output). So, I removed all the /RBO terms. Then I flipped all the “NOT” to be positive and all the positive to be “NOT”. Instead of !D0 AND !D2, the first term is D0 AND D2. Last, I ORd the lamp test (LT) with the results. The LT button is also inverted because pressing the button produces a zero. So you’ll notice that there is a !LT in each OR term. Since the segments are active low, I had to change all of my OR’s to NOR (the display looked rather interesting with the segments inverted).
The last part of the logic was forcing which display was on:
assign EN1 = 0; // enable digit 1 assign EN2 = 1; // disable digit 2 assign EN3 = 1; // disable digit 3
I wasn’t sure how large each Spartan 6 logic block was, so I just typed this in and expected the program to give me an error if I exceeded the number of AND/OR gates available. Apparently, I didn’t reach that limit. The program console shows that my program used 4 LUTs out of 5,720:
Slice Logic Utilization: Number of Slice Registers: 0 out of 11,440 0% Number of Slice LUTs: 4 out of 5,720 1% Number used as logic: 4 out of 5,720 1% Number using O6 output only: 1 Number using O5 output only: 0 Number using O5 and O6: 3 Number used as ROM: 0 Number used as Memory: 0 out of 1,440 0%
Apparently, the LUT (Look Up Table) is used to represent combinatorial circuits. There is a description of the LUT in this document: Spartan-6 FPGA Configurable Logic Block User Guide
The function generators in Spartan-6 FPGAs are implemented as six-input look-up tables (LUTs). There are six independent inputs (A inputs – A1 to A6) and two independent outputs (O5 and O6) for each of the four function generators in a slice (A, B, C, and D). The function generators can implement any arbitrarily defined six-input Boolean function. Basically, the LUT is a logic table representation of my discrete boolean logic. Technically, I could have provided a lookup table definition, similar to mapping out a circuit in Read Only Memory.
The Code
Here’s the full listing of the UCF file:
# User Constraint File for BCD to 7-Segment Hex Display implementation on Mimas V2 NET "A" LOC = A3; NET "B" LOC = B4; NET "C" LOC = A4; NET "D" LOC = C4; NET "E" LOC = C5; NET "F" LOC = D6; NET "G" LOC = C6; NET "EN1" LOC = B3; NET "EN2" LOC = A2; NET "EN3" LOC = B2; # Switches. # Internal pull-ups need to be enabled since # there is no pull-up resistor available on board NET "D0" PULLUP; NET "D1" PULLUP; NET "D2" PULLUP; NET "D3" PULLUP; NET "LT" PULLUP; NET "D0" LOC = F17; NET "D1" LOC = F18; NET "D2" LOC = E16; NET "D3" LOC = E18; NET "LT" LOC = M18;
And the V File:
module HexLED(D0,D1,D2,D3,LT, A, B, C, D, E, F, G, EN1, EN2, EN3); input wire D0; input wire D1; input wire D2; input wire D3; input wire LT; output wire A; output wire B; output wire C; output wire D; output wire E; output wire F; output wire G; output wire EN1; output wire EN2; output wire EN3; // /D0*/D2 + /D0*D3 + D1*D2 + D1*/D2*/D3 + D0*D2*/D3 + /D1*/D2*D3 and (a1, D0, D2); and (a2, D0, !D3); and (a3, !D1, !D2); and (a4, !D1, D2, D3); and (a5, !D0, !D2, D3); and (a6, D1, D2, !D3); nor (A, a1, a2, a3, a4, a5, a6, !LT); // /D2*/D3 + /D0*/D2 + /D0*/D1*/D3 + D0*D1*/D3 + D0*/D1*D3 and (b1, D2, D3); and (b2, D0, D2); and (b3, D0, D1, D3); and (b4, !D0, !D1, D3); and (b5, !D0, D1, !D3); nor (B, b1, b2, b3, b4, b5, !LT); // D0*/D1 + D0*/D2 + /D1*/D2 + D2*/D3 + /D2*D3 and (c1, !D0, D1); and (c2, !D0, D2); and (c3, D1, D2); and (c4, !D2, D3); and (c5, D2, !D3); nor (C, c1, c2, c3, c4, c5, !LT); // /D0*/D1*D3 + /D0*/D2*/D3 + D0*D1*/D2 + /D0*D1*D2 + D0*/D1*D2 and (d1, D0, D1, !D3); and (d2, D0, D2, D3); and (d3, !D0, !D1, D2); and (d4, D0, !D1, !D2); and (d5, !D0, D1, !D2); nor (D, d1, d2, d3, d4, d5, !LT); // /D0*/D2 + D2*D3 + /D0*D1 + D1*D3 and (e1, D0, D2); and (e2, !D2, !D3); and (e3, D0, !D1); and (e4, !D1, !D3); nor (E, e1, e2, e3, e4, !LT); // /D0*/D1 + /D2*D3 + D1*D3 + /D0*D2 + /D1*D2*/D3 and (f1, D0, D1); and (f2, D2, !D3); and (f3, !D1, !D3); and (f4, D0, !D2); and (f5, D1, !D2, D3); nor (F, f1, f2, f3, f4, f5, !LT); // D1*/D2 + D0*D3 + /D2*D3 + /D0*D1 + /D1*D2*/D3 and (g1, !D1, D2); and (g2, !D0, !D3); and (g3, D2, !D3); and (g4, D0, !D1); and (g5, D1, !D2, D3); nor (G, g1, g2, g3, g4, g5, !LT); assign EN1 = 0; // enable digit 1 assign EN2 = 1; // disable digit 2 assign EN3 = 1; // disable digit 3 endmodule