BASYS3 7-segment 켜보기
FPGA/BASYS3 2023. 12. 22. 01:42의식의 흐름대로 대충 적음
원래는 차근차근 다 회로도 짜고 블록도 짜고 그래야 하는데 그냥 다 안다는 가정하에 빠르게 켜보기만 하자
BASYS3 데이터 시트는 아래링크와 동영상 참고
https://digilent.com/reference/_media/basys3:basys3_rm.pdf
https://www.youtube.com/watch?v=ORhWNj8li4E
위 영상에서 나오는 코드를 아래에 복사해두었다.
만들고자 하는 로직
필요한 모듈
Top
10Hz generator
Digits
7 segment controller
1. 10Hz generator
Basys3 에서는 기본적으로 100Mhz 클럭을 제공하기 때문에 이를 10Hz로 변환해주어야함
`timescale 1ns / 1ps
module tenHz_generator(
input clk_100MHz,
input reset,
output clk_10Hz
);
reg [22:0] ctr_reg = 0; // 23 bits to cover 5,000,000
reg clk_out_reg = 0;
always @(posedge clk_100MHz or posedge reset)
if(reset) begin
ctr_reg <= 0;
clk_out_reg <= 0;
end
else
if(ctr_reg == 4_999_999) begin // 100MHz / 10Hz / 2 = 5,000,000
ctr_reg <= 0;
clk_out_reg <= ~clk_out_reg;
end
else
ctr_reg <= ctr_reg + 1;
assign clk_10Hz = clk_out_reg;
endmodule
2. Digits
`timescale 1ns / 1ps
module digits(
input clk_10Hz,
input reset,
output reg [3:0] ones,
output reg [3:0] tens,
output reg [3:0] hundreds,
output reg [3:0] thousands
);
// ones reg control
always @(posedge clk_10Hz or posedge reset)
if(reset)
ones <= 0;
else
if(ones == 9)
ones <= 0;
else
ones <= ones + 1;
// tens reg control
always @(posedge clk_10Hz or posedge reset)
if(reset)
tens <= 0;
else
if(ones == 9)
if(tens == 9)
tens <= 0;
else
tens <= tens + 1;
// hundreds reg control
always @(posedge clk_10Hz or posedge reset)
if(reset)
hundreds <= 0;
else
if(tens == 9 && ones == 9)
if(hundreds == 9)
hundreds <= 0;
else
hundreds <= hundreds + 1;
// thousands reg control
always @(posedge clk_10Hz or posedge reset)
if(reset)
thousands <= 0;
else
if(hundreds == 9 && tens == 9 && ones == 9)
if(thousands == 9)
thousands <= 0;
else
thousands <= thousands + 1;
endmodule
3. 7segment controller
`timescale 1ns / 1ps
module seg7_control(
input clk_100MHz,
input reset,
input [3:0] ones,
input [3:0] tens,
input [3:0] hundreds,
input [3:0] thousands,
output reg [0:6] seg, // segment pattern 0-9
output reg [3:0] digit // digit select signals
);
// Parameters for segment patterns
parameter ZERO = 7'b000_0001; // 0
parameter ONE = 7'b100_1111; // 1
parameter TWO = 7'b001_0010; // 2
parameter THREE = 7'b000_0110; // 3
parameter FOUR = 7'b100_1100; // 4
parameter FIVE = 7'b010_0100; // 5
parameter SIX = 7'b010_0000; // 6
parameter SEVEN = 7'b000_1111; // 7
parameter EIGHT = 7'b000_0000; // 8
parameter NINE = 7'b000_0100; // 9
// To select each digit in turn
reg [1:0] digit_select; // 2 bit counter for selecting each of 4 digits
reg [16:0] digit_timer; // counter for digit refresh
// Logic for controlling digit select and digit timer
always @(posedge clk_100MHz or posedge reset) begin
if(reset) begin
digit_select <= 0;
digit_timer <= 0;
end
else // 1ms x 4 displays = 4ms refresh period
if(digit_timer == 99_999) begin // The period of 100MHz clock is 10ns (1/100,000,000 seconds)
digit_timer <= 0; // 10ns x 100,000 = 1ms
digit_select <= digit_select + 1;
end
else
digit_timer <= digit_timer + 1;
end
// Logic for driving the 4 bit anode output based on digit select
always @(digit_select) begin
case(digit_select)
2'b00 : digit = 4'b1110; // Turn on ones digit
2'b01 : digit = 4'b1101; // Turn on tens digit
2'b10 : digit = 4'b1011; // Turn on hundreds digit
2'b11 : digit = 4'b0111; // Turn on thousands digit
endcase
end
// Logic for driving segments based on which digit is selected and the value of each digit
always @*
case(digit_select)
2'b00 : begin // ONES DIGIT
case(ones)
4'b0000 : seg = ZERO;
4'b0001 : seg = ONE;
4'b0010 : seg = TWO;
4'b0011 : seg = THREE;
4'b0100 : seg = FOUR;
4'b0101 : seg = FIVE;
4'b0110 : seg = SIX;
4'b0111 : seg = SEVEN;
4'b1000 : seg = EIGHT;
4'b1001 : seg = NINE;
endcase
end
2'b01 : begin // TENS DIGIT
case(tens)
4'b0000 : seg = ZERO;
4'b0001 : seg = ONE;
4'b0010 : seg = TWO;
4'b0011 : seg = THREE;
4'b0100 : seg = FOUR;
4'b0101 : seg = FIVE;
4'b0110 : seg = SIX;
4'b0111 : seg = SEVEN;
4'b1000 : seg = EIGHT;
4'b1001 : seg = NINE;
endcase
end
2'b10 : begin // HUNDREDS DIGIT
case(hundreds)
4'b0000 : seg = ZERO;
4'b0001 : seg = ONE;
4'b0010 : seg = TWO;
4'b0011 : seg = THREE;
4'b0100 : seg = FOUR;
4'b0101 : seg = FIVE;
4'b0110 : seg = SIX;
4'b0111 : seg = SEVEN;
4'b1000 : seg = EIGHT;
4'b1001 : seg = NINE;
endcase
end
2'b11 : begin // MINUTES ONES DIGIT
case(thousands)
4'b0000 : seg = ZERO;
4'b0001 : seg = ONE;
4'b0010 : seg = TWO;
4'b0011 : seg = THREE;
4'b0100 : seg = FOUR;
4'b0101 : seg = FIVE;
4'b0110 : seg = SIX;
4'b0111 : seg = SEVEN;
4'b1000 : seg = EIGHT;
4'b1001 : seg = NINE;
endcase
end
endcase
endmodule
5. Constraints.xdc 파일
# Clock signal
set_property PACKAGE_PIN W5 [get_ports clk_100MHz]
set_property IOSTANDARD LVCMOS33 [get_ports clk_100MHz]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk_100MHz]
#7 segment display
set_property PACKAGE_PIN W7 [get_ports {seg[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]
set_property PACKAGE_PIN W6 [get_ports {seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
set_property PACKAGE_PIN U8 [get_ports {seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
set_property PACKAGE_PIN V8 [get_ports {seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
set_property PACKAGE_PIN U5 [get_ports {seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
set_property PACKAGE_PIN V5 [get_ports {seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
set_property PACKAGE_PIN U7 [get_ports {seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
set_property PACKAGE_PIN U2 [get_ports {digit[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {digit[0]}]
set_property PACKAGE_PIN U4 [get_ports {digit[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {digit[1]}]
set_property PACKAGE_PIN V4 [get_ports {digit[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {digit[2]}]
set_property PACKAGE_PIN W4 [get_ports {digit[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {digit[3]}]
##Buttons
set_property PACKAGE_PIN U18 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
Synthesis 결과
Basys3에 돌려본 결과
참고자료 및 링크
https://www.fpga4student.com/2017/09/seven-segment-led-display-controller-basys3-fpga.html
[FPGA Tutorial] Seven-Segment LED Display on Basys 3 FPGA
FPGA tutorial guides you how to control the seven-segment LED display on Basys 3 FPGA Board. A display controller is designed and full Verilog code is provided.
www.fpga4student.com