要開始編寫verilog代碼了,以常用的分頻為例橘洞,編寫一個簡單的代碼婶肩。
FPGA設(shè)計中办陷,分頻分為偶數(shù)分頻和奇數(shù)分頻。
偶數(shù)分頻只要計上升沿的個數(shù)律歼,然后按照分頻要求的不同計相應(yīng)個數(shù)的上升沿并進(jìn)行波形翻轉(zhuǎn)即可懂诗。
例如二分頻,每計到一個上升沿苗膝,波形翻轉(zhuǎn)一次殃恒;
例如四分頻,每計到兩個上升沿辱揭,波形翻轉(zhuǎn)一次离唐。
奇數(shù)分頻相對比較麻煩,因為奇數(shù)分頻經(jīng)常要在給出時鐘的下降沿進(jìn)行翻轉(zhuǎn)问窃,而Verilog本質(zhì)上是硬件描述亥鬓,設(shè)計的本質(zhì)仍然是硬件設(shè)計。在綜合設(shè)計時域庇,Verilog代碼必須映射到FPGA上的可用硬件上嵌戈。
FPGA常用的電路是觸發(fā)器,觸發(fā)器是一個具有時鐘且僅對該時鐘的一個邊沿敏感的器件听皿。
always@(posedge clk)綜合后映射到只對一個時鐘邊沿敏感的觸發(fā)器熟呛,always@(posedge
clk or negedge rst)綜合后映射到有一個異步控制端且僅對時鐘的一個邊沿敏感的觸發(fā)器。
不管always@()綜合后映射到哪種觸發(fā)器尉姨,它都只能使用一個時鐘沿觸發(fā)庵朝。
奇數(shù)分頻注定要比偶數(shù)分頻復(fù)雜,可以采用這樣的方式進(jìn)行奇數(shù)分頻:
假設(shè)要對給定的時鐘進(jìn)行2N+1分頻:先計數(shù)又厉;將計數(shù)分成N九府、N+1的兩段;前一段將變量div1置0覆致,后一段將變量div1置1侄旬;用一個下降沿觸發(fā)的觸發(fā)器,div1延遲半個時鐘周期后輸出煌妈,生成div2儡羔;div1和div2相與婆排,即得到分頻后的時鐘。
module FreDivDou(
input? clk_i,
input? rst_n_i,
output div2_o,
output div3_o,
output div4_o,
output dou2_o,
output dou3_o
??? );
// 二分頻:在原來時鐘的上升沿翻轉(zhuǎn)
reg div2_o_r;
always @(posedge clk_i or negedge rst_n_i)
begin
? if(!rst_n_i)
??? div2_o_r <= 0;
? else
??? div2_o_r <= ~div2_o_r;
end
//div2_o_r要在always塊內(nèi)賦值笔链,需要定義成reg型
//assign相當(dāng)于一條連線段只,將表達(dá)式右邊的電路直接通過wire(線網(wǎng)型)連接到左邊,
//左邊信號必須是wire型(output屬于wire型)鉴扫。當(dāng)右邊變化時赞枕,左邊立刻發(fā)生變化。
assign div2_o = div2_o_r;?
//四分頻坪创,計數(shù)炕婶,每計夠兩個上升沿翻轉(zhuǎn)一次
reg [1:0]? counter_div4;
reg div4_o_r;
always @(posedge clk_i or negedge rst_n_i)
begin
? if(!rst_n_i)? begin
??? counter_div4 <= 0;
??? div4_o_r <= 0;
? end
? else
??? if(counter_div4 <= 0)begin
????? counter_div4 <= 'b1;
????? div4_o_r <= div4_o_r;
??? end
??? else if(counter_div4 <='b1) begin
???? counter_div4 <= 0;
????? div4_o_r <=~div4_o_r;
??? end???
?end
assign div4_o = div4_o_r;
//3分頻,第0個上升沿div1為1莱预,第1柠掂、2個上升沿div1為0
reg div1,div2;
reg [1:0] counter_div3;
always @(posedge clk_i or negedge rst_n_i)
begin
? if(!rst_n_i) begin
??? div1 <= 0;
??? counter_div3 <= 0;
? end
? else if(counter_div3 == 'd0)begin
??? div1 <= 'b1;
??? counter_div3 <=counter_div3 + 'b1;
? end
? else if(counter_div3 == 'd1)begin
??? div1 <= 0;
??? counter_div3 <=counter_div3 + 'b1;
? end
? else? begin
??? div1 <= 0;
??? counter_div3 <= 0;
? end
end
//3分頻,div1在時鐘的下降沿產(chǎn)生div2
always @(negedge clk_i or negedge rst_n_i)
if(!rst_n_i)
? div2 <= 0;
else
? div2 <= div1;
assign div3_o = div1 | div2;???
endmodule