AC620FPGA学习笔记——BCD数码管
BCD数码管
工程地址:https://github.com/HaHaHaHaHaGe/Planof2019_half/tree/master/Course_Project/FPGA/class03_hc595
实现8个8位数码管,根据分频后的时钟自动计数(16进制)
硬件结构
开发板:AC620
整体框架
BCDDisplay模块
根据输入的data每4位为1组,共8组,对应8个数码管,轮询进行刷新
device_74hc595模块
根据输入的并行数据输出串行数据,每次输出后会产生锁存脉冲(lock),在输出过程中会产生busy高电平信号,等传输完毕后恢复低电平。
代码部分
device_74hc595
module device_74hc595(
clk,
rst,
data,
busy,
lock,
lock595,
out595,
clk595
);
input clk,rst,lock;
input [15:0]data;
output reg lock595,clk595,busy,out595;
reg [4:0]send_cnt;
reg [15:0]data_buffer;
reg [1:0]flag;
localparam SEND_STATE = 2'b00;
localparam LOCK0_STATE = 2'b01;
localparam LOCK1_STATE = 2'b11;
localparam IDLE_STATE = 2'b10;
always@(posedge clk,negedge rst)
if(!rst)begin
send_cnt <= 5'b0;
busy <= 1'b0;
data_buffer <= 16'b0;
flag <= IDLE_STATE;
lock595 <= 1'b0;
clk595 <= 1'b1;
out595 <= 1'b0;
end
else
case(flag)
SEND_STATE:
if(clk595) begin
if(send_cnt == 5'd16)
flag <= LOCK0_STATE;
else begin
send_cnt <= send_cnt + 5'b1;
out595 <= data_buffer[5'd15-send_cnt];
clk595 <= 1'b0;
end
end
else begin
clk595 <= 1'b1;
end
LOCK0_STATE: begin
lock595 <= 1'b1;
flag <= LOCK1_STATE;
end
LOCK1_STATE: begin
lock595 <= 1'b0;
flag <= IDLE_STATE;
end
IDLE_STATE:
if(lock)begin
send_cnt <= 5'b0;
data_buffer <= data;
busy <= 1'b1;
flag <= SEND_STATE;
end
else
busy <= 1'b0;
default:
flag <= IDLE_STATE;
endcase
endmodule
BCDdecoder
module BCDdecoder(
data,
out
);
input [3:0]data;
output reg [7:0]out;
always@(*)
case(data)
4'h0:out = 7'b1000000;
4'h1:out = 7'b1111001;
4'h2:out = 7'b0100100;
4'h3:out = 7'b0110000;
4'h4:out = 7'b0011001;
4'h5:out = 7'b0010010;
4'h6:out = 7'b0000010;
4'h7:out = 7'b1111000;
4'h8:out = 7'b0000000;
4'h9:out = 7'b0010000;
4'ha:out = 7'b0001000;
4'hb:out = 7'b0000011;
4'hc:out = 7'b1000110;
4'hd:out = 7'b0100001;
4'he:out = 7'b0000110;
4'hf:out = 7'b0001110;
endcase
endmodule
frequencydivider
module frequencydivider(
clk,
rst,
fclk
);
input clk,rst;
output reg fclk;
reg [31:0]cnt;
always@(posedge clk,negedge rst)
if(!rst) begin
cnt <= 0;
fclk <= 0;
end
else if(cnt == 500) begin
cnt <= 0;
fclk <= ~fclk;
end
else
cnt <= cnt + 1;
endmodule
BCDDisplay
module BCDDisplay(
clk,
rst,
data,
lock595,
out595,
clk595
);
wire fclk;
input clk,rst;
input [31:0]data;
output lock595,out595,clk595;
reg flag;
reg [7:0]selecter;
reg [7:0]srcdata;
wire [7:0]dstdata;
reg [31:0]data_buffer;
reg lock;
wire busy;
reg doonce;
reg [7:0]cnt;
localparam Wait_Busy = 1'b0;
localparam Circle_Play = 1'b1;
BCDdecoder BCDdecoder_01(
.data(srcdata),
.out(dstdata)
);
frequencydivider frequencydivider_01(
.clk(clk),
.rst(rst),
.fclk(fclk)
);
device_74hc595 device_74hc595_01(
.clk(fclk),
.rst(rst),
.data({dstdata,selecter}),
.busy(busy),
.lock(lock),
.lock595(lock595),
.out595(out595),
.clk595(clk595)
);
always@(posedge clk,negedge rst)
if(!rst) begin
selecter <= 8'b0000_0001;
data_buffer <= 32'b0;
flag <= Circle_Play;
srcdata <= 8'b0;
lock <= 0;
cnt <= 8'd4;
doonce <= 0;
end
else begin
data_buffer <= data;
case(flag)
Circle_Play: begin
srcdata <= data_buffer >> cnt;
selecter <= {selecter[6:0],selecter[7]};
flag <= Wait_Busy;
doonce <= 0;
if(cnt == 8'd28)
cnt <= 8'b0;
else
cnt <= cnt + 4;
end
Wait_Busy:
if(busy) begin
lock <= 0;
doonce <= 1;
end
else if(doonce)
flag <= Circle_Play;
else
lock <= 1;
endcase
end
endmodule
顶层代码
module test_74hc595(
clk,
rst,
key,
lock595,
out595,
clk595
);
wire lock;
input clk;
input wire rst,key;
wire rst2;
reg [31:0]data;
output lock595,out595,clk595;
wire rst3;
wire clk2;
inkey inkey_1(
.in(key),
.out(lock),
.clk(clk)
);
inkey inkey_2(
.in(rst),
.out(rst2),
.clk(clk)
);
BCDDisplay BCDDisplay_1(
.clk(clk),
.rst(rst3),
.data(data),
.lock595(lock595),
.out595(out595),
.clk595(clk595)
);
frequencydivider frequencydivider2(
.clk(clk),
.rst(rst3),
.fclk(clk2)
);
always @(negedge rst3,posedge clk2)
begin
if(!rst3)
data <= 0;
else
data <= data + 1;
end
assign rst3 = ~rst2;
endmodule