一、 軟件平臺(tái)與硬件平臺(tái)
軟件平臺(tái):
1、操作系統(tǒng):Windows-8.1
2、開發(fā)套件:ISE14.7
硬件平臺(tái):
1、FPGA型號(hào):XC6SLX45-2CSG324
二、 原理介紹
我的開發(fā)板上有4個(gè)LED燈,原理圖如下:
由原理圖可知僅當(dāng)FPGA的對(duì)應(yīng)管腳輸入低電平時(shí)LED才會(huì)亮,流水燈的效果可以輪流讓四個(gè)對(duì)應(yīng)管腳輸出低電平來(lái)產(chǎn)生。
三、 目標(biāo)任務(wù)
編寫四個(gè)LED流水的Verilog代碼并用ModelSim進(jìn)行仿真,仿真通過(guò)以后下載到開發(fā)板進(jìn)行測(cè)試,要求開發(fā)板上每個(gè)LED亮的時(shí)間為1s。
四、 設(shè)計(jì)思路與Verilog代碼編寫
由于每個(gè)LED亮的時(shí)間為1s,所以首先很自然想到產(chǎn)生一個(gè)1s的時(shí)鐘用來(lái)驅(qū)動(dòng)后續(xù)邏輯,有了這個(gè)1s的時(shí)鐘以后,就可以在這個(gè)1s時(shí)鐘的節(jié)拍下對(duì)LED的輸出進(jìn)行以移位操作來(lái)產(chǎn)生流水燈的效果。
1、1s時(shí)鐘的分頻邏輯
由于主時(shí)鐘是50MHz,周期為20ns,所以可以利用50MHz主時(shí)鐘驅(qū)動(dòng)一個(gè)計(jì)數(shù)器,當(dāng)計(jì)數(shù)器的值每次到達(dá)24999999時(shí),消耗的時(shí)間為25000000*20ns=0.5s,這時(shí)把分頻器的輸出反轉(zhuǎn),并把計(jì)數(shù)值清0,這樣分頻器的輸出就會(huì)每隔0.5s翻轉(zhuǎn)一次,產(chǎn)生了一個(gè)1s的時(shí)鐘。
Verilog代碼如下:
////////////////////////////////////////////////////////////////// // 功能:產(chǎn)生1s的時(shí)鐘 ////////////////////////////////////////////////////////////////// always @(posedge I_clk or negedge I_rst_n) begin if(!I_rst_n) begin R_cnt_ls <= 32'd0 ; R_clk_ls_reg <= 1'b1 ; end else if(R_cnt_ls == 32'd24_999_999) begin R_cnt_ls <= 32'd0 ; R_clk_ls_reg <= ~R_clk_ls_reg ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end assign W_clk_ls = R_clk_ls_reg ;
2、移位邏輯
有了1s的時(shí)鐘信號(hào)以后,就在這個(gè)1s時(shí)鐘信號(hào)的驅(qū)動(dòng)下對(duì)輸出的LED寄存器進(jìn)行移位操作產(chǎn)生流水效果。
Verilog代碼如下:
////////////////////////////////////////////////////////////////// // 功能:對(duì)輸出寄存器進(jìn)行移位產(chǎn)生流水效果 ////////////////////////////////////////////////////////////////// always @(posedge W_clk_ls or negedge I_rst_n) begin if(!I_rst_n) R_led_out_reg <= 4'b0001 ; else if(R_led_out_reg == 4'b1000) R_led_out_reg <= 4'b0001 ; else R_led_out_reg <= R_led_out_reg << 1 ; end assign O_led_out = ~R_led_out_reg ;
五、 ModelSim仿真
寫好邏輯以后,為了確定時(shí)序是正確的,最好寫一個(gè)測(cè)試文件對(duì)功能進(jìn)行仿真,為了加快仿真速度,修改分頻邏輯計(jì)數(shù)器的計(jì)數(shù)值為24,然后編寫測(cè)試文件,測(cè)試文件中激勵(lì)產(chǎn)生的Verilog代碼如下:
initial begin // Initialize Inputs I_clk = 0; I_rst_n = 0; // Wait 100 ns for global reset to finish #100; I_rst_n = 1; // Add stimulus here end always #10 I_clk = ~I_clk ;
仿真的時(shí)序圖如下圖所示:
可以看到時(shí)序完全正確,接下來(lái)就是綁定管腳,生成bit文件下載到開發(fā)板測(cè)試了。
六、 進(jìn)一步思考——C語(yǔ)言流水燈與Verilog流水燈區(qū)別
看完網(wǎng)上《Verilog那些事》系列博文以后,作者提出了一種“仿順序操作”方法,其實(shí)以前自己寫代碼的時(shí)候無(wú)形之中一直在用這種思想,但是一直沒有提煉出來(lái),看完作者的介紹以后才發(fā)現(xiàn)確實(shí)是有那個(gè)“仿順序”的味道。詳細(xì)的博文請(qǐng)參考博客園博主akuei2的系列博文。這里我在總結(jié)一遍,給以后留個(gè)印象。
C語(yǔ)言實(shí)現(xiàn)流水燈的大致代碼框架如下:
while(1)
{
1、讓第1個(gè)LED亮,其他的滅;
2、延時(shí)1s
3、讓第2個(gè)LED亮,其他的滅
4、延時(shí)1s
5、讓第3個(gè)LED亮,其他的滅;
6、延時(shí)1s
7、讓第4個(gè)LED亮,其他的滅
8、延時(shí)1s
}
在while(1)里面代碼是一行一行的執(zhí)行,最后一行執(zhí)行完畢以后在回到第一行重新開始新一輪的執(zhí)行。就這樣產(chǎn)生了流水的效果。
看到這里,有人應(yīng)該突然明白了吧,這不正好就是Verilog中的一個(gè)狀態(tài)機(jī)么。對(duì)應(yīng)的Verilog代碼也可以寫出來(lái)了
always @(posedge I_clk)
begin
case(R_state)
第1個(gè)狀態(tài):讓第1個(gè)LED亮,其他的滅,下一狀態(tài)是第2個(gè)狀態(tài);
第2個(gè)狀態(tài):延時(shí)1s,下一狀態(tài)是第3個(gè)狀態(tài);
第3個(gè)狀態(tài):讓第2個(gè)LED亮,其他的滅,下一狀態(tài)是第4個(gè)狀態(tài);
第4個(gè)狀態(tài):延時(shí)1s,下一狀態(tài)是第5個(gè)狀態(tài);
第5個(gè)狀態(tài):讓第3個(gè)LED亮,其他的滅,下一狀態(tài)是第6個(gè)狀態(tài);
第6個(gè)狀態(tài):延時(shí)1s,下一狀態(tài)是第7個(gè)狀態(tài);
第7個(gè)狀態(tài):讓第4個(gè)LED亮,其他的滅,下一狀態(tài)是第8個(gè)狀態(tài);
第8個(gè)狀態(tài):延時(shí)1s,下一狀態(tài)是第1個(gè)狀態(tài);
default :;
endcase
end
具體的代碼如下:
////////////////////////////////////////////////////////////////// // 功能:“仿順序操作” ////////////////////////////////////////////////////////////////// always @(posedge I_clk or negedge I_rst_n) begin if(!I_rst_n) begin R_state <= 3'b000 ; R_cnt_ls <= 32'd0 ; end else begin case(R_state) C_S0: begin R_led_out_reg <= 4'b0001 ; R_state <= C_S1 ; end C_S1: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S2 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end C_S2: begin R_led_out_reg <= 4'b0010 ; R_state <= C_S3 ; end C_S3: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S4 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end C_S4: begin R_led_out_reg <= 4'b0100 ; R_state <= C_S5 ; end C_S5: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S6 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end C_S6: begin R_led_out_reg <= 4'b1000 ; R_state <= C_S7 ; end C_S7: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S0 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end default: R_state <= 3'b000 ; endcase end end assign O_led_out = ~R_led_out_reg ;
時(shí)序圖如下圖:
時(shí)序圖仍然正確,實(shí)現(xiàn)了流水燈的效果
七、 總結(jié)
1、所謂的“仿順序操作”實(shí)際上就是一個(gè)狀態(tài)機(jī),通過(guò)狀態(tài)的跳變實(shí)現(xiàn)“順序執(zhí)行”的效果。這種思想在后面寫接口時(shí)序的時(shí)候還是挺管用的,今后可以多多琢磨琢磨。
2、 C語(yǔ)言的while(1)和Verilog語(yǔ)言的always @(posedge I_clk)有類似的地方,只要CPU的時(shí)鐘存在,它們就一直執(zhí)行下去。書上都說(shuō)C語(yǔ)言是一種串行語(yǔ)言,Verilog是一種并行語(yǔ)言,實(shí)際上這里也能有體會(huì):C語(yǔ)言里只能有1個(gè)while(1)語(yǔ)句,進(jìn)入while(1)以后CPU就出不來(lái)了,而Verilog中可以有多個(gè)always @(posedge I_clk)語(yǔ)句,并且每個(gè)always @(posedge I_clk)同時(shí)運(yùn)行的,這就是兩種語(yǔ)言最大的區(qū)別吧。
八、 附錄
1、分頻1s產(chǎn)生流水燈的完整代碼
module led_work_top ( input I_clk , input I_rst_n , output [3:0] O_led_out ); reg [31:0] R_cnt_ls ; wire W_clk_ls ; reg R_clk_ls_reg ; reg [3:0] R_led_out_reg ; ////////////////////////////////////////////////////////////////// // 功能:產(chǎn)生1s的時(shí)鐘 ////////////////////////////////////////////////////////////////// always @(posedge I_clk or negedge I_rst_n) begin if(!I_rst_n) begin R_cnt_ls <= 32'd0 ; R_clk_ls_reg <= 1'b1 ; end else if(R_cnt_ls == 32'd24_999_999) begin R_cnt_ls <= 32'd0 ; R_clk_ls_reg <= ~R_clk_ls_reg ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end assign W_clk_ls = R_clk_ls_reg ; ////////////////////////////////////////////////////////////////// // 功能:對(duì)輸出寄存器進(jìn)行移位產(chǎn)生流水效果 ////////////////////////////////////////////////////////////////// always @(posedge W_clk_ls or negedge I_rst_n) begin if(!I_rst_n) R_led_out_reg <= 4'b0001 ; else if(R_led_out_reg == 4'b1000) R_led_out_reg <= 4'b0001 ; else R_led_out_reg <= R_led_out_reg << 1 ; end assign O_led_out = ~R_led_out_reg ; endmodule
2、 “仿順序操作”產(chǎn)生流水燈完整代碼
module led_work_top ( input I_clk , input I_rst_n , output [3:0] O_led_out ); reg [31:0] R_cnt_ls ; reg [3:0] R_led_out_reg ; reg [2:0] R_state ; parameter C_CNT_1S = 32'd49_999_999 ; parameter C_S0 = 3'b000 , C_S1 = 3'b001 , C_S2 = 3'b010 , C_S3 = 3'b011 , C_S4 = 3'b100 , C_S5 = 3'b101 , C_S6 = 3'b110 , C_S7 = 3'b111 ; ////////////////////////////////////////////////////////////////// // 功能:仿順序操作 ////////////////////////////////////////////////////////////////// always @(posedge I_clk or negedge I_rst_n) begin if(!I_rst_n) begin R_state <= 3'b000 ; R_cnt_ls <= 32'd0 ; end else begin case(R_state) C_S0: begin R_led_out_reg <= 4'b0001 ; R_state <= C_S1 ; end C_S1: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S2 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end C_S2: begin R_led_out_reg <= 4'b0010 ; R_state <= C_S3 ; end C_S3: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S4 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end C_S4: begin R_led_out_reg <= 4'b0100 ; R_state <= C_S5 ; end C_S5: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S6 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end C_S6: begin R_led_out_reg <= 4'b1000 ; R_state <= C_S7 ; end C_S7: begin if(R_cnt_ls == C_CNT_1S) begin R_cnt_ls <= 32'd0 ; R_state <= C_S0 ; end else R_cnt_ls <= R_cnt_ls + 1'b1 ; end default: R_state <= 3'b000 ; endcase end end assign O_led_out = ~R_led_out_reg ; endmodule
3、測(cè)試記錄文件完整代碼
module tb_led_work_top; // Inputs reg I_clk; reg I_rst_n; // Outputs wire [3:0] O_led_out; // Instantiate the Unit Under Test (UUT) led_work_top U_led_work_top ( .I_clk(I_clk), .I_rst_n(I_rst_n), .O_led_out(O_led_out) ); initial begin // Initialize Inputs I_clk = 0; I_rst_n = 0; // Wait 100 ns for global reset to finish #100; I_rst_n = 1; // Add stimulus here end always #5 I_clk = ~I_clk ; endmodule
審核編輯:湯梓紅
-
FPGA
+關(guān)注
關(guān)注
1629文章
21738瀏覽量
603459 -
led
+關(guān)注
關(guān)注
242文章
23278瀏覽量
660939 -
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110106 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136860 -
流水燈
+關(guān)注
關(guān)注
21文章
433瀏覽量
59718
原文標(biāo)題:【接口時(shí)序】2、Verilog實(shí)現(xiàn)流水燈及與C語(yǔ)言的對(duì)比
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論