The 7-segments display consists of 8 LEDs (let's not forget the dot) aggregated as shown below.
Each segment is created using a separate LED, typically named "A" to "G", plus DP for the dot. So a 7-segments display consists of 8 LEDs. Now, the LEDs are not wired separately. To save a few pins in the 7-segments display, either the anodes or the cathodes are tied together, so that only 9 pins are required out of the display. For example, here's a common-cathode display:Such a display requires at least 9 pins. It is often made in 10 pins packages (and the common signal is available on two pins).
Now, to drive such a display from an FPGA, the straightforward solution is to use 8 IOs.
module LED_7seg(segA, segB, segC, segD, segE, segF, segG, segDP); output segA, segB, segC, segD, segE, segF, segG, segDP; assign {segA, segB, segC, segD, segE, segF, segG, segDP} = 8'b11011010; // light the leds to display '2' endmoduleNow that wasn't too hard.
module LED_7seg( input clk, output segA, segB, segC, segD, segE, segF, segG, segDP ); reg [23:0] cnt; // we use a 24bit counter always @(posedge clk) cnt <= cnt + 24'h1; // to count up to 16 million wire cntovf = &cnt; // so that this is active once every second reg [3:0] BCD; // BCD is a counter always @(posedge clk) if(cntovf) // that increments every second BCD <= (BCD==4'h9 ? 4'dh0 : BCD+4'h1); // from 0 to 9 reg [7:0] SevenSeg; always @(*) case(BCD) 4'h0: SevenSeg = 8'b11111100; 4'h1: SevenSeg = 8'b01100000; 4'h2: SevenSeg = 8'b11011010; 4'h3: SevenSeg = 8'b11110010; 4'h4: SevenSeg = 8'b01100110; 4'h5: SevenSeg = 8'b10110110; 4'h6: SevenSeg = 8'b10111110; 4'h7: SevenSeg = 8'b11100000; 4'h8: SevenSeg = 8'b11111110; 4'h9: SevenSeg = 8'b11110110; default: SevenSeg = 8'b00000000; endcase assign {segA, segB, segC, segD, segE, segF, segG, segDP} = SevenSeg; endmodule
module LED_7seg( input clk, output segA, segB, segC, segD, segE, segF, segG, segDP ); reg [23:0] cnt; always @(posedge clk) cnt <= cnt+24'h1; wire cntovf = &cnt; reg [3:0] BCD_new, BCD_old; always @(posedge clk) if(cntovf) BCD_new <= (BCD_new==4'h9 ? 4'h0 : BCD_new+4'h1); always @(posedge clk) if(cntovf) BCD_old <= BCD_new; reg [4:0] PWM; wire [3:0] PWM_input = cnt[22:19]; always @(posedge clk) PWM <= PWM[3:0]+PWM_input; wire [3:0] BCD = (cnt[23] | PWM[4]) ? BCD_new : BCD_old; reg [7:0] SevenSeg; always @(*) case(BCD) 4'h0: SevenSeg = 8'b11111100; 4'h1: SevenSeg = 8'b01100000; 4'h2: SevenSeg = 8'b11011010; 4'h3: SevenSeg = 8'b11110010; 4'h4: SevenSeg = 8'b01100110; 4'h5: SevenSeg = 8'b10110110; 4'h6: SevenSeg = 8'b10111110; 4'h7: SevenSeg = 8'b11100000; 4'h8: SevenSeg = 8'b11111110; 4'h9: SevenSeg = 8'b11110110; default: SevenSeg = 8'b00000000; endcase assign {segA, segB, segC, segD, segE, segF, segG, segDP} = SevenSeg; endmodule
Nice, isn't it?
Sorry you have to build it if you want to see it.