在verilog程序設(shè)計(jì)中,我們往往要對(duì)一個(gè)頻率進(jìn)行任意分頻,而且占空比也有一定的要求這樣的話,對(duì)于程序有一定的要求,現(xiàn)在我在前人經(jīng)驗(yàn)的基礎(chǔ)上做一個(gè)簡單的總結(jié),實(shí)現(xiàn)對(duì)一個(gè)頻率的任意占空比的任意分頻。
比如:我們FPGA系統(tǒng)時(shí)鐘是50M Hz,而我們要產(chǎn)生的頻率是880Hz,那么,我們需要對(duì)系統(tǒng)時(shí)鐘進(jìn)行分頻。我們很容易想到用計(jì)數(shù)的方式來分頻:
50000000/880 = 56818
這個(gè)數(shù)字不是2的整冪次方,那么怎么辦呢?我們可以設(shè)定一個(gè)參數(shù),讓它到56818的時(shí)候重新計(jì)數(shù)不就完了嗎?呵呵,程序如下:
module div(clk, clk_div);
input clk;
output clk_div;
reg [15:0] counter;
always @(posedge clk)
if(counter==56817) counter <= 0;
else counter <= counter+1;
assign clk_div = counter[15];
endmodule
下面我們來算一下它的占空比:我們清楚地知道,這個(gè)輸出波形在counter為0到32767的時(shí)候?yàn)榈?,?2767到56817的時(shí)候?yàn)楦?,占空比?0%多一些,如果我們需要占空比為50%,那么怎么辦呢?不用急,慢慢來。
我們?cè)僭O(shè)定一個(gè)參數(shù),使它為56817的一半,使達(dá)到它的時(shí)候波形翻轉(zhuǎn),那不就完了嗎?呵呵,再看看:
module div(clk, clk_div); input clk; output clk_div; reg [14:0] counter; always @(posedge clk) if(counter==28408) counter <= 0; else counter <= counter+1; reg clk_div; always @(posedge clk) if(counter==28408) clk_div <= ~clk_div; endmodule
占空比是不是神奇地變成50%了呢?呵呵。
繼續(xù)讓我們來看如何實(shí)現(xiàn)任意占空比,比如還是由50 M分頻產(chǎn)生880 Hz,而分頻得到的信號(hào)的占空比為30%。
56818×30%=17045
module div(clk,reset,clk_div,counter); input clk,reset; output clk_div; output [15:0] counter; reg [15:0] counter; reg clk_div; always @(posedge clk) if(!reset) counter <= 0; else if(counter==56817) counter <= 0; else counter <= counter+1; always @(posedge clk) if(!reset) clk_div <= 0; else if(counter<17045) clk_div <= 1; else clk_div <= 0; endmodule
三分頻的Verilog實(shí)現(xiàn)
//很實(shí)用也是筆試面試時(shí)??嫉?,已經(jīng)經(jīng)過仿真
占空比要求50%和不要求占空比差別會(huì)很大,先看一個(gè)占空比50%的描述
module div3(CLKIN,CLKOUT,RESETn); input CLKIN,RESETn; output CLKOUT; //internal counter signals reg[1:0] count_a; reg[1:0] count_b; reg CLKOUT; always @(negedge RESETn or posedge CLKIN) begin if (RESETn==1'b0) count_a<=2'b00; else if (count_a==2'b10) count_a<=2'b00; else count_a<=count_a+1; end always @(negedge RESETn or negedge CLKIN) begin if (RESETn==1'b0) count_b<=2'b0; else if (count_b==2'b10) count_b<=2'b00; else count_b<=count_b+1; end always @(count_a or count_b or RESETn) begin if (RESETn==1'b0) CLKOUT=1'b0; else if((count_a+count_b==4)||(count_a+ count_b==1)) CLKOUT=~CLKOUT; end endmodule
0 1 2 0 1 2
/ / / /
0 1 2 0 1 2
下面是一個(gè)非50%的描述,只用了上升沿
module div3(CLKIN,CLKOUT,RESETn); input CLKIN,RESETn; output CLKOUT; wire d; reg q1,q2; wire CLKOUT; always @(negedge RESETn or posedge CLKIN) begin if (RESETn==1'b0) q1<=1'b0; else q1<=d; end always @(negedge RESETn or posedge CLKIN) begin if (RESETn==1'b0) q2<=1'b0; else q2<=q1; end assign d=~q1 & ~q2; assign CLKOUT=q2; endmodule
占空比不是50%,只用了單沿觸發(fā)器,寄存器輸出。
至于其他奇數(shù)要求50%的或者不要求的占空比的,都可以參照上面兩個(gè)例子做出。
占空比為50%的一個(gè)更好的實(shí)現(xiàn)。
module div3(CLKIN,CLKOUT,RESETn); input CLKIN,RESETn; output CLKOUT; //internal counter signals reg[1:0] count_a; reg b,c; //reg CLKOUT; wire CLKOUT; always @(negedge RESETn or posedge CLKIN) begin if (RESETn==1'b0) count_a<=2'b00; else if (count_a==2'b10) count_a<=2'b00; else count_a<=count_a+1; end always @(negedge RESETn or negedge CLKIN) begin if (RESETn==1'b0) b<=1'b0; else if (count_a==2'b01) b<=2'b0; else b<=1'b1; end always @(negedge RESETn or posedge CLKIN) begin if (RESETn==1'b0) c<=1'b0; else if (count_a==2'b10) c<=1'b1; else if (count_a==2'b01) c<=1'b0; end assign CLKOUT=b & c; endmodule
時(shí)鐘選擇器的Verilog寫法!
CPRI有3種數(shù)據(jù)時(shí)鐘,61.44M 122.88M 245.76M,需要模塊能夠根據(jù)外部的速率指示信號(hào)(一個(gè)2位的輸入信號(hào),由模塊外部給定)選擇其中的一種時(shí)鐘作為模塊的工作時(shí)鐘
但由于所選用的FPGA工作頻率關(guān)系,不能超過400M,無法通過寄存器方式實(shí)現(xiàn)時(shí)鐘源的選擇.
使用雙邊觸發(fā)的方式將最高的頻率進(jìn)行分頻,代碼如下,已經(jīng)通過ModelSim的仿真,可以實(shí)現(xiàn)。
module clk_div( reset, //復(fù)位信號(hào) data_rate, //數(shù)據(jù)速率指示 clk2, //245.76M的時(shí)鐘輸入 time1, //分頻計(jì)數(shù)器 clk //選擇后的時(shí)鐘輸出 ); input reset; input [1:0] data_rate; input clk2; output [1:0] time1; output clk; reg [1:0] time1; reg clk; always@(clk2 or reset) if(reset) begin time1=2'b00; clk=1'b0; end else begin time1=time1+1'b1; case(data_rate) 2'b00:if(time1==2'b00) clk=~clk; else clk=clk; 2'b01:if(time1[0]==1'b1) clk=~clk; else clk=clk; 2'b10:clk=clk; 2'b11:clk=~clk; endcase end endmodule
verilog 實(shí)現(xiàn)gray碼計(jì)數(shù)器
//16位gray碼計(jì)數(shù)器,gary碼狀態(tài)改變時(shí)候每次只改變一個(gè)bit //,可以有效防止競(jìng)爭和毛刺的產(chǎn)生。 module gray_counter(clk,clr,start,stop,q,cout); input clk; input clr; input start,stop; output reg [3:0] q; output reg cout; reg flag=1; reg [3:0] s,next_s; //parameter S0=0, S1=1, S2=2, S3=3, S4=4, S5=5, S6=6, S7=7; //parameter S8=8, S9=9, S10=10, S11=11, S12=12, S13=13, S14=14, S15=15; parameter s0=0000, s1=0001, s2=0011, s3=0010; parameter s4=0110, s5=0111, s6=0101, s7=0100; parameter s8=1100, s9=1101, s10=1111,s11=1110; parameter s12=1010, s13=1011, s14=1001, s15=1000; always @(posedge clk) begin if (clr) s <= s0; else s <= next_s; end /*always @(posedge start or posedge stop) begin if(start) flag=1; else if (stop) flag=0; end*/ always @(s or flag) /*該進(jìn)程實(shí)現(xiàn)狀態(tài)的轉(zhuǎn)換*/ begin case (s) s0: begin if (flag) next_s <=s1; // else next_s <=s0; end s1: begin if (flag) next_s <= s2; end s2: begin if (flag) next_s <=s3; ////else next_s <=s0; end s3: begin if (flag) next_s <=s4; //else next_s <=s3; end s4: begin if (flag) next_s <= s5; end s5: begin if (flag) next_s <=s6; //else next_s <=s0; end s6: begin if (flag) next_s <=s7; //else next_s <=s3; end s7: begin if (flag) next_s <=s8; //else next_s <=s0; end s8: begin if (flag) next_s <= s9; end s9: begin if (flag) next_s <=s10; ////else next_s <=s0; end s10: begin if (flag) next_s <=s11; //else next_s <=s3; end s11: begin if (flag) next_s <= s12; end s12: begin if (flag) next_s <=s13; //else next_s <=s0; end s13: begin if (flag) next_s <=s14; //else next_s <=s3; end s14: begin if (flag) next_s <=s15; ////else next_s <=s0; end s15: begin if (flag) next_s <=s0; //else next_s <=s3; end default: next_s <=s0; /*default語句*/ endcase end always @(s) /*該進(jìn)程定義組合邏輯(FSM的輸出)*/ begin case(s) s0: q=0; s1: q=4; s2: q=2; s3: q=3; s4: q=4; s5: q=5; s6: q=6; s7: q=7; s8: q=8; s9: q=9; s10: q=10; s11: q=11; s12: q=12; s13: q=13; s14: q=14; s15: q=15; default:q=0; /*default語句,避免鎖存器的產(chǎn)生*/ endcase end always @(s) begin if (s==s15) cout=1;//assign cout=q; else cout=0; end endmodule
審核編輯:郭婷
-
FPGA
+關(guān)注
關(guān)注
1630文章
21766瀏覽量
604575 -
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110181
原文標(biāo)題:Verilog_實(shí)現(xiàn)任意占空比、任意分頻的方法
文章出處:【微信號(hào):ZYNQ,微信公眾號(hào):ZYNQ】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論