本次實(shí)驗(yàn)(一)見博客:【數(shù)字電路與系統(tǒng)】【北京航空航天大學(xué)】實(shí)驗(yàn):時序邏輯設(shè)計——三色燈開關(guān)(一)、實(shí)驗(yàn)指導(dǎo)書
說明:本次實(shí)驗(yàn)的代碼使用verilog編寫,文章中為閱讀方便,故采用matlab代碼格式。
實(shí)驗(yàn)二、時序邏輯設(shè)計——三色燈開關(guān)(實(shí)驗(yàn)報告部分)
2、實(shí)驗(yàn)報告
2.1、需求分析
本次實(shí)驗(yàn)要求設(shè)計一種通過操作開關(guān)的時間控制燈光顏色的開關(guān),該燈具含有兩組LED白光燈芯和兩組LED黃光燈芯,且開關(guān)的功能大致分為四種情況:
1、 如果燈具發(fā)出白光時斷開開關(guān),且在1秒之內(nèi)再次閉合開關(guān),則燈具發(fā)出日光;
2、 如果燈具發(fā)出日光時斷開開關(guān),且在1秒之內(nèi)再次閉合開關(guān),則燈具發(fā)出黃光;
3、 如果燈具發(fā)出黃光時斷開開關(guān),則再次閉合開關(guān)之后,燈具發(fā)出白光;
4、 如果開關(guān)斷開的時間超過1秒,則開關(guān)閉合后,燈具發(fā)出白光。
因此可以總結(jié)出該燈具大致的工作流程為:白光——日光——黃光——白光,且時延Δt = 1秒,故可以設(shè)置cnt變量用于計時。
擴(kuò)展實(shí)驗(yàn)要求:
開發(fā)時序邏輯電路,將按動開關(guān)的操作(“開”、“關(guān)”)以及按動開關(guān)之間的時間間隔(以
10ms為單位,進(jìn)行0~127編碼,分別代表0s至1.27s,超過1.27s均算作1.27s)以數(shù)碼的形式“錄制”下來,記錄深度至少為16條操作序列(至少能保存16次操作);
按動實(shí)驗(yàn)板上的一個按鍵,可以將記錄的內(nèi)容用UART依次上傳并顯示到PC機(jī)終端上。
2.2、系統(tǒng)設(shè)計
2.2.1、總體設(shè)計思路
模塊:按照設(shè)計需求,分為 “mode_run” 模塊 & “mode_demo” 模塊以及用于按鍵去抖的debounce模塊。
由于題目要求延時一定時間后重新設(shè)定狀態(tài),故可以設(shè)置一cnt變量用于計時;使用RESET進(jìn)行復(fù)位。
拓展實(shí)驗(yàn):
通過Uart_ClkDiv進(jìn)行時鐘分頻,Key進(jìn)行按鍵消抖,Uart_Tx作為上傳數(shù)據(jù)模塊,time_cnt作為記錄數(shù)據(jù)并依次上傳模塊。
2.2.2、接口設(shè)計
mode_run:
input clk (系統(tǒng)時鐘), rst (重置);
key0 (按鍵0) LOC = P2;
key1 (按鍵1) LOC = P3;
NET "led[0]" LOC = P79;
NET "led[1]" LOC = P83;
NET "led[2]" LOC = P84;
NET "led[3]" LOC = P85;
NET "clk" LOC = P36;
NET "rst" LOC = P11;
NET "key0" LOC = P2;
NET "key1" LOC = P3;
mode_demo:
NET "light[0]" LOC = P23;
NET "light[1]" LOC = P18;
NET "light[2]" LOC = P15;
NET "light[3]" LOC = P16;
NET "light[4]" LOC = P17;
NET "light[5]" LOC = P22;
NET "light[6]" LOC = P24;
NET "clk" LOC = P36;
NET "dp" LOC = P12;
NET "com[0]" LOC = P27;
NET "com[1]" LOC = P26;
NET "key0" LOC = P2;
NET "key1" LOC = P3;
NET "rst" LOC = P11;
Uart_time:
NET "Sys_CLK" LOC = P36;
NET "Key_In[0]" LOC = P32;
NET "Key_In[1]" LOC = P2;
NET "Sys_RST" LOC = P11;
NET "Sys_RST" PULLUP;
NET "Signal_Tx" LOC = P10;
2.2.3、mode_run模塊
圖 1 狀態(tài)機(jī)流程圖
module mode_run_1(
clk,
rst,
key0,
key1,
led
);
input clk ;
input rst ;
input key0 ;
input key1 ;
wire key_0 ;
wire key_1 ;
output reg [3:0] led ;
debounce instance_name0 (
.clk(clk),
.rst(rst),
.key(key0),
.key_pulse(key_0)
);
debounce instance_name1 (
.clk(clk),
.rst(rst),
.key(key1),
.key_pulse(key_1)
);
reg [24:0] cnt ;
parameter C_25M = 25'd24_999_999;
//信號定義
reg [3:0] state_b ;
//狀態(tài)機(jī)參數(shù)
parameter S0 = 4'b0000 ;
parameter S1 = 4'b0001 ;
parameter S2 = 4'b0011 ;
parameter S3 = 4'b0101 ;
parameter S4 = 4'b1111 ;
parameter S5 = 4'b0100 ;
parameter S6 = 4'b1100 ;
initial begin
state_b <= S0;
led <= S0;
cnt <= 25'b0;
end
//一段式狀態(tài)機(jī)
always@(posedge clk or negedge rst) begin
if(!rst) begin
state_b <= S0;
led <= S0;
cnt <= 25'b0;
end
else begin
if(key_0 == 1) cnt <= 25'b0;
else cnt <= cnt + 1;
if(cnt >= C_25M && led == S0)
state_b <= S0;
else state_b <= state_b;
case(led)
S0: begin
if(key_0 == 1) begin
case(state_b)
S0: begin
state_b <= S1;
led <= S1;
end
S1: begin
state_b <= S3;
led <= S3;
end
S2: begin
state_b <= S4;
led <= S4;
end
S3: begin
state_b <= S5;
led <= S5;
end
S4: begin
state_b <= S6;
led <= S6;
end
S5: begin
state_b <= S1;
led <= S1;
end
S6: begin
state_b <= S2;
led <= S2;
end
default: begin
state_b <= state_b;
led <= led;
end
endcase
end
else begin
led <= S0;
end
end
S1: begin
if(key_0 == 1) begin
state_b <= S1;
led <= S0;
end
else if(key_1 == 1) begin
state_b <= S2;
led <= S2;
end
end
S2: begin
if(key_0 == 1) begin
state_b <= S2;
led <= S0;
end
else if(key_1 == 1) begin
state_b <= S1;
led <= S1;
end
end
S3: begin
if(key_0 == 1) begin
state_b <= S3;
led <= S0;
end
else if(key_1 == 1) begin
state_b <= S4;
led <= S4;
end
end
S4: begin
if(key_0 == 1) begin
state_b <= S4;
led <= S0;
end
else if(key_1 == 1) begin
state_b <= S3;
led <= S3;
end
end
S5: begin
if(key_0 == 1) begin
state_b <= S5;
led <= S0;
end
else if(key_1 == 1) begin
state_b <= S6;
led <= S6;
end
end
S6: begin
if(key_0 == 1) begin
state_b <= S6;
led <= S0;
end
else if(key_1 == 1) begin
state_b <= S5;
led <= S5;
end
end
default: begin
state_b <= state_b;
led <= led;
end
endcase
end
end
endmodule
2.2.4、debounce模塊
該模塊為防抖模塊。對按鍵KEY進(jìn)行消抖,達(dá)到輸入信號穩(wěn)定且有效的目的。
2.2.5、mode_demo模塊
module mode_demo_1(
clk,
rst,
key0,
key1,
dp,
light,
com
);
input clk ;
input rst ;
input key0 ;
input key1 ;
wire key_0 ;
wire key_1 ;
output reg [1:0] com ;
output reg dp ;
output reg [6:0] light ;
debounce instance_name0 (
.clk(clk),
.rst(rst),
.key(key0),
.key_pulse(key_0)
);
debounce instance_name1 (
.clk(clk),
.rst(rst),
.key(key1),
.key_pulse(key_1)
);
//信號定義
reg [3:0] state_b ;
reg [3:0] state_c ;
//狀態(tài)機(jī)參數(shù)
parameter S0 = 4'b0000 ;
parameter S1 = 4'b0001 ;
parameter S2 = 4'b0011 ;
parameter S3 = 4'b0101 ;
parameter S4 = 4'b1111 ;
parameter S5 = 4'b0100 ;
parameter S6 = 4'b1100 ;
//數(shù)碼管譯碼
parameter DATA0 = 7'b0111111 ;
parameter DATA1 = 7'b0000110 ;
parameter DATA2 = 7'b1011011 ;
parameter DATA3 = 7'b1001111 ;
parameter DATA4 = 7'b1100110 ;
parameter DATA5 = 7'b1101101 ;
parameter DATA6 = 7'b1111101 ;
parameter DATA7 = 7'b0000111 ;
parameter DATA8 = 7'b1111111 ;
parameter DATA9 = 7'b1101111 ;
reg sec_pls; //產(chǎn)生秒脈沖
reg [25:0] sec_cnt;
always@(posedge clk or negedge rst) begin
if(key_0 == 1) begin
sec_pls <= 1'b0;
sec_cnt <= 26'b0;
end
else begin
sec_pls <= sec_pls;
sec_cnt <= sec_cnt;
end
if(!rst) begin
sec_pls <= 1'b0;
sec_cnt <= 26'b0;
end
else if(sec_cnt == 26'd50_000_000) begin
sec_pls <= 1'b1;
sec_cnt <= 26'b0;
end
else begin
sec_pls <= 1'b0;
sec_cnt <= sec_cnt + 1;
end
end
reg [6:0] sec;
reg [3:0] tmp;
reg [3:0] num;
reg [3:0] buf0;
reg [3:0] buf1;
reg dp1;
//計數(shù)器,約10ms掃描一次,用于數(shù)碼管動態(tài)顯示
reg [16:0] cnt;
always@(posedge clk or negedge rst) begin
if(!rst) cnt <= 17'b0;
else if(cnt == 17'b11111111111111111) begin
cnt <= 17'b0;
end
else cnt <= cnt + 1;
end
always@(posedge clk or negedge rst) begin
if(!rst) begin
state_c <= S0;
state_b <= S0;
dp <= 0;
end
else begin
if(sec >= 10 && state_c == S0)
state_b <= S0;
else state_b <= state_b;
case(state_c)
S0: begin
if(key_0 == 1) begin
case(state_b)
S0: begin
state_b <= S1;
state_c <= S1;
end
S1: begin
state_b <= S3;
state_c <= S3;
end
S2: begin
state_b <= S4;
state_c <= S4;
end
S3: begin
state_b <= S5;
state_c <= S5;
end
S4: begin
state_b <= S6;
state_c <= S6;
end
S5: begin
state_b <= S1;
state_c <= S1;
end
S6: begin
state_b <= S2;
state_c <= S2;
end
default: begin
state_b <= state_b;
state_c <= state_c;
end
endcase
end
else begin
state_b <= state_b;
state_c <= S0;
end
end
S1: begin
if(key_0 == 1) begin
state_b <= S1;
state_c <= S0;
end
else if(key_1 == 1) begin
state_b <= S2;
state_c <= S2;
end
end
S2: begin
if(key_0 == 1) begin
state_b <= S2;
state_c <= S0;
end
else if(key_1 == 1) begin
state_b <= S1;
state_c <= S1;
end
end
S3: begin
if(key_0 == 1) begin
state_b <= S3;
state_c <= S0;
end
else if(key_1 == 1) begin
state_b <= S4;
state_c <= S4;
end
end
S4: begin
if(key_0 == 1) begin
state_b <= S4;
state_c <= S0;
end
else if(key_1 == 1) begin
state_b <= S3;
state_c <= S3;
end
end
S5: begin
if(key_0 == 1) begin
state_b <= S5;
state_c <= S0;
end
else if(key_1 == 1) begin
state_b <= S6;
state_c <= S6;
end
end
S6: begin
if(key_0 == 1) begin
state_b <= S6;
state_c <= S0;
end
else if(key_1 == 1) begin
state_b <= S5;
state_c <= S5;
end
end
default: begin
state_c <= state_c;
state_b <= state_b;
end
endcase
end
if(key_0 == 1) begin
sec <= 7'b0;
num <= 4'b0;
com <= 2'b00;
light <= DATA0;
end
else sec <= sec;
if(!rst) begin
sec <= 7'b0;
light <= DATA0;
end
else if(sec_pls) begin
if(sec == 7'd99) begin
sec <= 7'b0;
num <= 4'b0;
light <= DATA0;
end
else begin
sec <= sec + 1;
case(state_c) //dp位表示狀態(tài)
S0: begin
if(sec >= 7'd10) state_b <= S0;
else state_b <= state_b;
end
S2: begin
dp1 <= ~dp1;
end
S4: begin
dp1 <= ~dp1;
end
S6: begin
dp1 <= ~dp1;
end
endcase
end
end
//顯示模塊
if(!rst) begin
num <= 4'b0;
com <= 2'b00;
end
else begin
if(sec >= 0 && sec < 10) begin //數(shù)碼管顯示數(shù)字
buf1 <= 0;
buf0 <= sec[3:0];
end
else if(sec >= 10 && sec < 20) begin
buf1 <= 4'd1;
tmp <= (sec - 7'd10);
buf0 <= tmp[3:0];
end
else if(sec >= 20 && sec < 30) begin
buf1 <= 4'd2;
tmp <= sec - 7'd20;
buf0 <= tmp[3:0];
end
else if(sec >= 30 && sec < 40) begin
buf1 <= 4'd3;
tmp <= sec - 7'd30;
buf0 <= tmp[3:0];
end
else if(sec >= 40 && sec < 50) begin
buf1 <= 4'd4;
tmp <= sec - 7'd40;
buf0 <= tmp[3:0];
end
else if(sec >= 50 && sec < 60) begin
buf1 <= 4'd5;
tmp <= sec - 7'd50;
buf0 <= tmp[3:0];
end
else if(sec >= 60 && sec < 70) begin
buf1 <= 4'd6;
tmp <= sec - 7'd60;
buf0 <= tmp[3:0];
end
else if(sec >= 70 && sec < 80) begin
buf1 <= 4'd7;
tmp <= sec - 7'd70;
buf0 <= tmp[3:0];
end
else if(sec >= 80 && sec < 90) begin
buf1 <= 4'd8;
tmp <= sec - 7'd80;
buf0 <= tmp[3:0];
end
else if(sec >= 90 && sec < 100) begin
buf1 <= 4'd9;
tmp <= sec - 7'd90;
buf0 <= tmp[3:0];
end
case(cnt[16])
1'b0: begin
com <= 2'b01;
num <= buf0;
case(state_c)
S0: dp <= 0;
S1: dp <= 1;
S2: dp <= dp1;
S3: dp <= 1;
S4: dp <= dp1;
S5: dp <= 0;
S6: dp <= 0;
default: dp <= 0;
endcase
end
1'b1: begin
com <= 2'b10;
num <= buf1;
case(state_c)
S0: dp <= 0;
S1: dp <= 0;
S2: dp <= 0;
S3: dp <= 1;
S4: dp <= dp1;
S5: dp <= 1;
S6: dp <= dp1;
default: dp <= 0;
endcase
end
endcase
case(num) //個位
4'd0: light <= DATA0;
4'd1: light <= DATA1;
4'd2: light <= DATA2;
4'd3: light <= DATA3;
4'd4: light <= DATA4;
4'd5: light <= DATA5;
4'd6: light <= DATA6;
4'd7: light <= DATA7;
4'd8: light <= DATA8;
4'd9: light <= DATA9;
default: light <= DATA0;
endcase
end
end
endmodule
2.2.6、time_cnt模塊
module time_cnt(Sys_CLK,Sys_RST,Idle,Key_In,send_data,send_en
);
input Sys_CLK;
input Sys_RST;
input Idle;
input [1:0]Key_In;
output reg [7:0] send_data;
output reg send_en;
reg key0_d1;
reg key0_d2;
reg key1_d1;
reg key1_d2;
reg [7:0] time_cnt;
reg [3:0] send_cnt;
reg [17:0]Div_Cnt = 18'd0; //
reg Div_CLK_10ms = 1'b0;
reg Div_CLK_10ms_d1 = 1'b0;
reg Div_CLK_10ms_d2 = 1'b0;
reg cnt_flag;
reg send_flag;
reg [7:0] send_data_reg [0:15];
always@(posedge Sys_CLK or negedge Sys_RST)
begin
if(!Sys_RST)begin
key0_d1 <= 1'b0;
key0_d2 <= 1'b0;
Div_CLK_10ms_d1 <= 1'b0;
Div_CLK_10ms_d2 <= 1'b0;
end
else
begin
key0_d1 <= Key_In[0];
key0_d2 <= key0_d1;
Div_CLK_10ms_d1 <= Div_CLK_10ms;
Div_CLK_10ms_d2 <= Div_CLK_10ms_d1;
end
end
always@(posedge Div_CLK_10ms or negedge Sys_RST)
begin
if(!Sys_RST)begin
key1_d1 <= 1'b0;
key1_d2 <= 1'b0;
end
else
begin
key1_d1 <= Key_In[1];
key1_d2 <= key1_d1;
end
end
always@(posedge Sys_CLK)
begin
if(Div_Cnt == 18'd250000)
begin
Div_Cnt = 18'd0;
Div_CLK_10ms = ~Div_CLK_10ms;
end
else
Div_Cnt = Div_Cnt + 1'd1;
end
always@(posedge Sys_CLK or negedge Sys_RST)
begin
if(!Sys_RST)begin
time_cnt <= 8'd0;
cnt_flag <= 1'b0;
end
else if(key0_d1 && !key0_d2) //rise
begin
time_cnt <= 8'd0;
cnt_flag <= 1'b1;
end
else if(!key0_d1 && key0_d2) //fall
begin
time_cnt <= 8'd0;
cnt_flag <= 1'b0;
end
else if(cnt_flag && Div_CLK_10ms_d1 && !Div_CLK_10ms_d2)
begin
time_cnt <= time_cnt + 8'd1;
end
end
always@(posedge Sys_CLK or negedge Sys_RST)begin
if(!Sys_RST)
begin
send_data_reg[0] <= 8'd0;
send_data_reg[1] <= 8'd0;
send_data_reg[2] <= 8'd0;
send_data_reg[3] <= 8'd0;
send_data_reg[4] <= 8'd0;
send_data_reg[5] <= 8'd0;
send_data_reg[6] <= 8'd0;
send_data_reg[7] <= 8'd0;
send_data_reg[8] <= 8'd0;
send_data_reg[9] <= 8'd0;
send_data_reg[10] <= 8'd0;
send_data_reg[11] <= 8'd0;
send_data_reg[12] <= 8'd0;
send_data_reg[13] <= 8'd0;
send_data_reg[14] <= 8'd0;
send_data_reg[15] <= 8'd0;
// send_data_reg[12] <= 8'd31;
// send_data_reg[13] <= 8'd42;
// send_data_reg[14] <= 8'd53;
// send_data_reg[15] <= 8'd64;
end
else if(!key0_d1 && key0_d2)
begin
send_data_reg[0] <= time_cnt;
send_data_reg[1] <= send_data_reg[0];
send_data_reg[2] <= send_data_reg[1];
send_data_reg[3] <= send_data_reg[2];
send_data_reg[4] <= send_data_reg[3];
send_data_reg[5] <= send_data_reg[4];
send_data_reg[6] <= send_data_reg[5];
send_data_reg[7] <= send_data_reg[6];
send_data_reg[8] <= send_data_reg[7];
send_data_reg[9] <= send_data_reg[8];
send_data_reg[10] <= send_data_reg[9];
send_data_reg[11] <= send_data_reg[10];
send_data_reg[12] <= send_data_reg[11];
send_data_reg[13] <= send_data_reg[12];
send_data_reg[14] <= send_data_reg[13];
send_data_reg[15] <= send_data_reg[14];
end
end
always@(posedge Div_CLK_10ms or negedge Sys_RST)
begin
if(!Sys_RST)begin
send_data <= 8'd0;
send_en <= 1'b0;
send_flag <= 1'b0;
end
else if(key1_d1 && !key1_d2)
begin
send_data <= send_data_reg[0];
send_en <= 1'b1;
send_flag <= 1'b1;
end
else if(send_flag && !Idle && send_en == 1'b0 && send_cnt < 4'd15)
begin
send_data <= send_data_reg[send_cnt];
// send_data <= send_data_reg[0];
send_en <= 1'b1;
send_flag <= 1'b1;
end
else if(send_flag && !Idle && send_en == 1'b0 && send_cnt == 4'd15)
begin
// send_data <= send_data_reg[send_cnt];
send_data <= send_data_reg[15];
send_en <= 1'b1;
send_flag <= 1'b0;
end
else
begin
send_en <= 1'b0;
end
end
always@(posedge Div_CLK_10ms or negedge Sys_RST)
begin
if(!Sys_RST)begin
send_cnt <= 4'd0;
end
else if(send_cnt < 4'd15 && send_en )
begin
send_cnt <= send_cnt + 4'd1;
end
end
endmodule
其他模塊都已經(jīng)在用例中給出,此處不再贅述。文章來源:http://www.zghlxwxcb.cn/news/detail-858852.html
(未完待續(xù))文章來源地址http://www.zghlxwxcb.cn/news/detail-858852.html
到了這里,關(guān)于【數(shù)字電路與系統(tǒng)】【北京航空航天大學(xué)】實(shí)驗(yàn):時序邏輯設(shè)計——三色燈開關(guān)(二)、需求分析和系統(tǒng)設(shè)計的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!