Created
August 8, 2023 01:18
-
-
Save LispEngineer/95da27ead5474653c105bcafa328f491 to your computer and use it in GitHub Desktop.
Digilent Basys3 7-segment driver in SystemVerilog
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Douglas P. Fields, Jr. 2023-08 | |
// 7-segment hexadecimal driver for Digilent Basys3 board | |
`timescale 1ns / 1ps | |
module seven_segment ( | |
input logic [3:0] num, | |
output logic [6:0] hex | |
); | |
// Purpose: Creates a case statement for all possible input binary numbers. | |
// Drives hex appropriately for each input combination. | |
always_comb | |
unique case (num) | |
4'b0000 : hex = 7'b011_1111; // 7E; | |
4'b0001 : hex = 7'b000_0110; // 30; | |
4'b0010 : hex = 7'b101_1011; // 6D; | |
4'b0011 : hex = 7'b100_1111; // 79; | |
4'b0100 : hex = 7'b110_0110; // 33; | |
4'b0101 : hex = 7'b110_1101; // 5B; | |
4'b0110 : hex = 7'b111_1101; // 5F; | |
4'b0111 : hex = 7'b000_0111; // 70; | |
4'b1000 : hex = 7'b111_1111; // 7F; | |
4'b1001 : hex = 7'b110_1111; // 7B; | |
4'b1010 : hex = 7'b111_0111; // 77; | |
4'b1011 : hex = 7'b111_1100; // 1F; | |
4'b1100 : hex = 7'b011_1001; // 4E; | |
4'b1101 : hex = 7'b101_1110; // 3D; | |
4'b1110 : hex = 7'b111_1001; // 4F; | |
4'b1111 : hex = 7'b111_0001; // 47; | |
endcase | |
endmodule: seven_segment | |
module multiplex_seg #( | |
// This works nicely with: | |
// 50_000_000 (ha) | |
// There is no visible ghosting in normal room lighting at: | |
// 50_000 | |
// There is visible ghosting at: (regardless of using PULLTYPE PULLUP in XDC on cathodes or not) | |
// 5_000 | |
// 1_000 | |
// This fails miserably with: | |
// 10 | |
CYCLES = 50_000 // Cannot be < 1 | |
) ( | |
input logic clk, | |
// 1 means light that segment | |
input logic [7:0] seg_in [4], | |
// 0 means light that segment when an is also 0 | |
output logic [7:0] seg_out, | |
output logic [3:0] an | |
); | |
if (CYCLES < 1) begin | |
$error("CYCLES must be positive"); | |
end | |
localparam CYCLE_BITS = $clog2(CYCLES); | |
// localparam CYCLE_BITS_HIGH = CYCLE_BITS - 1; | |
// localparam CYCLE_START_INT = CYCLES - 1; | |
localparam CYCLE_START = CYCLE_BITS'(CYCLES - 1); | |
logic [CYCLE_BITS-1:0] cycle = '0; | |
logic [1:0] digit = '0; | |
always_comb @(posedge clk) begin | |
if (cycle == '0) begin | |
cycle <= CYCLE_START; | |
digit <= digit + 1'd1; | |
an <= 4'b1111; | |
an[digit] <= 1'b0; | |
seg_out <= ~seg_in[digit]; | |
end else begin | |
cycle <= cycle - 1'd1; | |
end | |
end | |
endmodule: multiplex_seg | |
module top ( | |
input logic clk, // 100 MHz | |
input logic [15:0] sw, | |
input logic [4:0] btn, | |
output logic [15:0] led, | |
output logic [7:0] seg, // 7 segment displays; #7 is the decimal point | |
output logic [3:0] an // anodes for the 7 segment displays | |
); | |
logic [7:0] seg4 [4]; | |
genvar i; | |
for (i = 0; i < 4; i++) begin | |
// Details on +: | |
// https://stackoverflow.com/questions/17778418/what-is-and | |
seven_segment hex_to_seg (.num(sw[(i * 4) +: 4]), .hex(seg4[i])); | |
end | |
assign led = sw; | |
multiplex_seg seg_display ( | |
.clk(clk), | |
.seg_in(seg4), | |
.seg_out(seg), | |
.an(an) | |
); | |
endmodule: top |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment