1. 為了更好地學習FPGA和深入理解Verilog語法,首先從最簡單的流水燈做起。雖然簡單,但是也包含了不少知識。通過這次實驗項目,可以了解開發軟件的使用及Verilog的編程方法,熟悉模塊化設計的方法。
2. 該項目主要實現的功能為:
(1)10位的流水燈
(2)中間兩個led燈每隔100ms閃爍一次
(3)兩邊的led燈每隔100ms流動一下,從中間向兩邊流水。
3. 具體實現如下
(1)首先定義一個時間計數寄存器counter,每當達到預定的100ms時,計數寄存器就清零,否則的話寄存器就加1。然后計算計數器計數的最大值。時鍾頻率為50MHZ,也就是周期為1/50M 為20ns,要計數的最大值為T100MS= 100ms/20ns-1 = 4999_999。
代碼實現為
always @ (posedge clk or negedge rst)
if(!rst) //高電平復位
counter<=25'd0;
else if(counter==T100ms)
counter<=25'd0;
else
counter<=counter+1'b1;
(2)如何控制led的亮滅呢,無非就是給端口賦高低電平,有的是高電平亮,有的是低電平亮,我用的FPGA學習板為高電平亮。每隔100ms對其端口值取反就可以實現閃爍的led
(3)流水燈的實現。在FPGA中實現流水燈的方法有很多種,我只列取了三種供參考學習。首先是運用FPGA的並行處理特點,建立四個always模塊分別對每隔led分別控制,也可以建立四個模塊分別對各個燈控制。所對應的時序圖如圖1-a,每一個模塊控制相應的led燈,彼此之間互不影響,依靠總的時鍾進行工作。
圖1-a
這種方法能夠充分體現FPGA並行處理的特點,實現起來也很容易。
頂層代碼為
moduletop_module(CLK, RSTn, LED_Out);
input CLK;
input RSTn;
output [3:0]LED_Out;
wire LED1_Out;
led1_module U1
(
.CLK(CLK),
.RSTn(RSTn),
.LED_Out(LED1_Out)
);
wire LED2_Out;
led2_module U2
(
.CLK(CLK),
.RSTn(RSTn),
.LED_Out(LED2_Out)
);
wire LED3_Out;
led3_module U3
(
.CLK(CLK),
.RSTn(RSTn),
.LED_Out(LED3_Out)
);
wire LED4_Out;
led4_module U4
(
.CLK(CLK),
.RSTn(RSTn),
.LED_Out(LED4_Out)
);
assign LED_Out = {LED4_Out, LED3_Out,LED2_Out, LED1_Out};
第二種方法為循環移位法。通過給led賦初值,然后循環左移或者循環右移,但是需要設置一個條件。否則就會出現溢出的情況。如圖2-a設置一個條件當要出現溢出的時候讓它回到初始的狀態,這樣就可以實現流水了。
圖2-a
代碼實現為
always @(posedge clk or negedge rst)
if(!rst)
led<=4'b0001; //初值,最低位led[0]燈亮
else if(counter==T100ms)
begin
if(led==4'b0000) //當溢出最高位時
led<=4'b0001; //回到復位時的狀態
else
led<=led<<1; //循環左移一位
end
第三種數據拼接法,所謂的數據拼接就把原來的數據拆成一位一位的,在特定位置上拼接上一個數。例如在4位的led的低位拼接一個1. Led[3:0]<={led[2:0],1’b1};接即實現了數據的拼接,當然可以實現任意位,任意bit數的拼。和循環移位類似,數據拼接的實現只是把移位命令改成拼接的命令即可。