AC620FPGA學習筆記——BCD數碼管
阿新 • • 發佈:2018-11-17
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;
[email protected](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;
[email protected](*)
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;
[email protected](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)
);
[email protected](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