FPGA學(xué)習:PLL分頻計數的LED閃爍實(shí)例
如圖8.17所示,本實(shí)例將用到FPGA內部的PLL資源,輸入FPGA引腳上的25MHz時(shí)鐘,配置PLL使其輸出4路分別為12.5MHz、25MHz、50MHz和100MHz的時(shí)鐘信號,這4路時(shí)鐘信號又分別驅動(dòng)4個(gè)不同位寬的計數器不停的計數工作,這些計數器的最高位最終輸出用于控制4個(gè)不同的LED亮滅。由于這4個(gè)時(shí)鐘頻率都有一定的倍數關(guān)系,所以我們也很容易通過(guò)調整合理的計數器位寬,達到4個(gè)LED閃爍一致的控制。
本文引用地址:http://dyxdggzs.com/article/201804/379162.htm

cy4.v模塊代碼解析
先來(lái)看cy4.v模塊的代碼,它是工程的頂層模塊,主要做接口定義和模塊例化,一般不會(huì )在這個(gè)模塊中做任何的具體邏輯設計。
首先是接口部分,只有時(shí)鐘、復位和8個(gè)LED信號。
module cy4(
input ext_clk_25m, //外部輸入25MHz時(shí)鐘信號
input ext_rst_n, //外部輸入復位信號,低電平有效
output[7:0] led //8個(gè)LED指示燈接口
);
接著(zhù)這里申明5個(gè)wire類(lèi)型的信號,所有在不同模塊間接口的信號,在它們的上級模塊中都必須定義為wire類(lèi)型,這里有4個(gè)不同頻率的時(shí)鐘以及由PLL的lock信號引出的復位信號sys_rst_n。
wire clk_12m5; //PLL輸出12.5MHz時(shí)鐘
wire clk_25m; //PLL輸出25MHz時(shí)鐘
wire clk_50m; //PLL輸出50MHz時(shí)鐘
wire clk_100m; //PLL輸出100MHz時(shí)鐘
wire sys_rst_n; //PLL輸出的locked信號,作為FPGA內部的復位信號,低電平復位,高電平正常工作
PLL是我們配置的IP核模塊,它需要在我們的代碼中例化,如下所示。
//-------------------------------------
//PLL例化
pll_controller pll_controller_inst (
.areset ( !ext_rst_n ),
.inclk0 ( ext_clk_25m ),
.c0 ( clk_12m5 ),
.c1 ( clk_25m ),
.c2 ( clk_50m ),
.c3 ( clk_100m ),
.locked ( sys_rst_n )
);
最后4個(gè)LED閃爍控制模塊的例化,它們的源碼都是led_controller.v模塊,但它們的名稱(chēng)不一樣,分別為uut_led_controller_clk12m5、uut_led_controller_clk25m、uut_led_controller_clk50m、uut_led_controller_clk100m。這樣的定義方式最終實(shí)現效果不同于軟件的函數調用,軟件的函數調用只有一個(gè)函數,分時(shí)復用;而FPGA的這種代碼例化卻會(huì )實(shí)現4個(gè)完全一樣的硬件邏輯。當然了,這4個(gè)模塊還略有不同,就是兩個(gè)名稱(chēng)中間的“#(n)”,n有23、24、25和26,這個(gè)是輸入到led_controller.v模塊的一個(gè)參數,大家別急,后面我們馬上就會(huì )提到它。
//-------------------------------------
//12.5MHz時(shí)鐘進(jìn)行分頻閃爍,計數器為23位
led_controller #(23) uut_led_controller_clk12m5(
.clk(clk_12m5), //時(shí)鐘信號
.rst_n(sys_rst_n), //復位信號,低電平有效
.sled(led[0]) //LED指示燈接口
);
//-------------------------------------
//25MHz時(shí)鐘進(jìn)行分頻閃爍,計數器為24位
led_controller #(24) uut_led_controller_clk25m(
.clk(clk_25m), //時(shí)鐘信號
.rst_n(sys_rst_n), //復位信號,低電平有效
.sled(led[1]) //LED指示燈接口
);
//-------------------------------------
//25MHz時(shí)鐘進(jìn)行分頻閃爍,計數器為25位
led_controller #(25) uut_led_controller_clk50m(
.clk(clk_50m), //時(shí)鐘信號
.rst_n(sys_rst_n), //復位信號,低電平有效
.sled(led[2]) //LED指示燈接口
);
//-------------------------------------
//25MHz時(shí)鐘進(jìn)行分頻閃爍,計數器為26位
led_controller #(26) uut_led_controller_clk100m(
.clk(clk_100m), //時(shí)鐘信號
.rst_n(sys_rst_n), //復位信號,低電平有效
.sled(led[3]) //LED指示燈接口
);
//-------------------------------------
//高4位LED指示燈關(guān)閉
assign led[7:4] = 4'b1111;
endmodule
led_controller.v模塊代碼解析
led_controller.v模塊代碼如下,這里重點(diǎn)注意我們上面剛剛提到的輸入參數。在代碼中,有“parameter CNT_HIGH = 24;”這樣的定義,若是例化這個(gè)模塊的上層接口中不定義“#(n)”,則表示“parameter CNT_HIGH = 24;”語(yǔ)句生效,若是定義的“#(n)”中的n值與代碼中定義的24不同,那么以n為最終值。
module led_controller(
input clk, //時(shí)鐘信號
input rst_n, //復位信號,低電平有效
output sled //LED指示燈接口
);
parameter CNT_HIGH = 24; //計數器最高位
//-------------------------------------
reg[(CNT_HIGH-1):0] cnt; //24位計數器
//cnt計數器進(jìn)行循環(huán)計數
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt <= 0;
else cnt <= cnt+1'b1;
assign sled = cnt[CNT_HIGH-1];
endmodule
評論