計數器 FPGA電路實驗 作業2
實驗內容 1
使用Veriog - HDL 語言,DE0 FPGA 開發板 按照如下要求設計一個計數器電路 。
功能描述
在 DE0 開發板的 最右側 的 HEX LED 數碼管上,進行計數並用十進位制數進行顯示。計數器特徵如下:
只能使用一個50MHz的時鐘訊號,不要有計數器分頻的訊號作為時鐘
該計數器在電路復位後會迴圈的從0值遞增計數到最大值,計數最大值是一個迴圈變化的過程,計數器復位之後,第一次計數最大值是6,然後是7、8、9,然後計數最大值又變成6,如此往復迴圈, 計數數值變化的時間間隔是1秒 ,計數過程如下所示:
0 1 … 6 | 0 1 … 7 | 0 1 … 8 | 0 1 … 9 | 0 1 … 6 | …… |
---|
人工繪製的電路結構RTL設計圖
頂層BDF圖如下:
1.div模組為分頻器用於將50MHz時鐘訊號分頻產生1s時鐘訊號在clk_div輸出。
2.count模組為產生符合技術要求的計數器。
3.decoder_hex模組為4-7譯碼器,譯碼使在數碼管上顯示對應字元。
div模組人工繪製的RTL圖:
Quartus掃描生成的電路RTL圖
計數器的計數值的SignalTap截圖
實驗程式碼
******************分頻器程式碼******************
module div(
clk , // clock
reset,
CNTVAL, // counter value
clk_div); // overflow
input clk;
input reset;
output [32-1:0] CNTVAL;
output clk_div;
parameter MAX_VAL = 50_000_000; //50MHz下為1s
reg [32-1:0] CNTVAL;
reg clk_div;
always @ (posedge clk)
begin
if (!reset)
begin
CNTVAL <= 0;
end
else
begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
end
always @ (CNTVAL) begin
if(CNTVAL == MAX_VAL)
clk_div = 1'b1;
else
clk_div = 1'b0;
end
endmodule
******************計數器程式碼******************
module count(
clk,
cnt,
OV);
input clk,rst;
output reg[3:0] cnt;
output OV;
reg[1:0] state,next_state;
reg[3:0] cnt_temp;
parameter s0=2'b00,s1=2'b01,s2=2'b11,s3=2'b10;
[email protected]( next_state or rst)
begin
if(rst)
begin
state=s0;
cnt=0;
end
else
begin
state=next_state;
cnt=cnt_temp;
end
end
[email protected](posedge clk)
begin
if(state == s0 && cnt == 0)
begin
cnt_temp=0;
next_state=s0;
end
case(state)
s0:begin
if(cnt_temp>=6)
begin
cnt_temp=0;
next_state=s1;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
s1:begin
if(cnt_temp>=7)
begin
cnt_temp=0;
next_state=s2;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
s2:begin
if(cnt_temp>=8)
begin
cnt_temp=0;
next_state=s3;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
s3:begin
if(cnt_temp>=9)
begin
cnt_temp=0;
next_state=s0;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
default:begin
next_state=s0;
cnt_temp=0;
end
endcase
end
endmodule
******************數碼管譯碼器程式碼******************
module decoder_hex(
data_in,
EN,
data_out);
input [3:0] data_in ;
input EN ;
output [6:0] data_out ;
reg [6:0] data_out ;
always @(data_in or EN )
begin
data_out = 7'b1111111;
if (EN == 1)
case (data_in)
4'b0000: data_out = 7'b1000000; // 0
4'b0001: data_out = 7'b1111001; // 1
4'b0010: data_out = 7'b0100100; // 2
4'b0011: data_out = 7'b0110000; // 3
4'b0100: data_out = 7'b0011001; // 4
4'b0101: data_out = 7'b0010010; // 5
4'b0110: data_out = 7'b0000011; // 6
4'b0111: data_out = 7'b1111000; // 7
4'b1000: data_out = 7'b0000000; // 8
4'b1001: data_out = 7'b0011000; // 9
4'b1010: data_out = 7'b0001000; // A
4'b1011: data_out = 7'b0000011; // b
4'b1100: data_out = 7'b1000110; // c
4'b1101: data_out = 7'b0100001; // d
4'b1110: data_out = 7'b0000110; // E
4'b1111: data_out = 7'b0001110; // F
default: data_out = 7'b1111111; //不顯示
endcase
end
endmodule
計數過程連結
===================================================
實驗內容 2
功能描述
在 DE0 開發板的 從左到右 的 4個HEX LED 數碼管上,進行計數並用十進位制數進行顯示。計數器特徵如下
只能使用一個50MHz的時鐘訊號,不要有計數器分頻的訊號作為時鐘
系統復位後全部HEX LED熄滅
左1 LED,顯示 0、1、2 ~6 ,然後熄滅
左2 LED,顯示 0、1、2 ~7 ,然後熄滅
左3 LED,顯示 0、1、2 ~8 ,然後熄滅
最右側 LED,顯示 0、1、2 ~9 ,然後熄滅
然後再開始左1 LED, 顯示 0、1、2~6 如此一直迴圈。
所有情況下,計數數值變化的時間間隔是1秒
人工繪製的電路結構RTL設計圖
頂層BDF圖如下:
1.div模組為分頻器用於將50MHz時鐘訊號分頻產生1s時鐘訊號在clk_div輸出。
2.count模組為產生符合技術要求的計數器。
3.decoder_hex模組為4-7譯碼器,譯碼使在數碼管上顯示對應字元。
4.select模組OV端輸出訊號分別使能四個譯碼器,產生移位效果。
select模組人工繪製的RTL圖:
Quartus掃描生成的電路RTL圖
Quartus掃描生成的電路select模組RTL圖:
狀態機的狀態轉移圖和表示式:
計數器的計數值的SignalTap截圖
實驗程式碼
******************分頻器程式碼******************
module div(
clk , // clock
reset,
CNTVAL, // counter value
clk_div); // overflow
input clk;
input reset;
output [32-1:0] CNTVAL;
output clk_div;
parameter MAX_VAL = 50_000_000; //50MHz下為1s
reg [32-1:0] CNTVAL;
reg clk_div;
always @ (posedge clk)
begin
if (!reset)
begin
CNTVAL <= 0;
end
else
begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
end
always @ (CNTVAL) begin
if(CNTVAL == MAX_VAL)
clk_div = 1'b1;
else
clk_div = 1'b0;
end
endmodule
******************計數器程式碼******************
module count(
clk,
cnt,
OV);
input clk,rst;
output reg[3:0] cnt;
output OV;
reg[1:0] state,next_state;
reg[3:0] cnt_temp;
parameter s0=2'b00,s1=2'b01,s2=2'b11,s3=2'b10;
[email protected]( next_state or rst)
begin
if(rst)
begin
state=s0;
cnt=0;
end
else
begin
state=next_state;
cnt=cnt_temp;
end
end
[email protected](posedge clk)
begin
if(state == s0 && cnt == 0)
begin
cnt_temp=0;
next_state=s0;
end
case(state)
s0:begin
if(cnt_temp>=6)
begin
cnt_temp=0;
next_state=s1;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
s1:begin
if(cnt_temp>=7)
begin
cnt_temp=0;
next_state=s2;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
s2:begin
if(cnt_temp>=8)
begin
cnt_temp=0;
next_state=s3;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
s3:begin
if(cnt_temp>=9)
begin
cnt_temp=0;
next_state=s0;
end
else
begin
cnt_temp=cnt_temp+1;
end
end
default:begin
next_state=s0;
cnt_temp=0;
end
endcase
end
endmodule
******************數碼管譯碼器程式碼******************
module decoder_hex(
data_in,
EN,
data_out);
input [3:0] data_in ;
input EN ;
output [6:0] data_out ;
reg [6:0] data_out ;
always @(data_in or EN )
begin
data_out = 7'b1111111;
if (EN == 1)
case (data_in)
4'b0000: data_out = 7'b1000000; // 0
4'b0001: data_out = 7'b1111001; // 1
4'b0010: data_out = 7'b0100100; // 2
4'b0011: data_out = 7'b0110000; // 3
4'b0100: data_out = 7'b0011001; // 4
4'b0101: data_out = 7'b0010010; // 5
4'b0110: data_out = 7'b0000011; // 6
4'b0111: data_out = 7'b1111000; // 7
4'b1000: data_out = 7'b0000000; // 8
4'b1001: data_out = 7'b0011000; // 9
4'b1010: data_out = 7'b0001000; // A
4'b1011: data_out = 7'b0000011; // b
4'b1100: data_out = 7'b1000110; // c
4'b1101: data_out = 7'b0100001; // d
4'b1110: data_out = 7'b0000110; // E
4'b1111: data_out = 7'b0001110; // F
default: data_out = 7'b1111111; //不顯示
endcase
end
endmodule
******************選擇器程式碼******************
module select(
IN ,
RESET ,
OV );
input IN;
input RESET;
output OV;
parameter ST_INIT = 4'b0000;
parameter ST_0 = 4'b0001;
parameter ST_1 = 4'b0010;
parameter ST_2 = 4'b0100;
parameter ST_3 = 4'b1000;
reg[3:0] OV_temp;
reg[3:0] OV;
[email protected](RESET)
begin
if(RESET)
begin
OV<=ST_INIT;
end
else
begin
OV<=OV_temp;
end
end
always @ (posedge IN) begin
case (OV_temp)
ST_0 :begin if(IN==1) OV_temp <= ST_1 ; else OV_temp <= ST_0; end
ST_1 :begin if(IN==1) OV_temp <= ST_2 ; else OV_temp <= ST_1; end
ST_2 :begin if(IN==1) OV_temp <= ST_3 ; else OV_temp <= ST_2; end
ST_3 :begin if(IN==1) OV_temp <= ST_0 ; else OV_temp <= ST_3; end
endcase
end
endmodule