1、位寬太小
在FPGA設(shè)計(jì)中,我們經(jīng)常需要用寄存器來(lái)寄存某些“數(shù)量類”的變量,比如FIFO的深度啦、或者計(jì)數(shù)器的最大值啦;又或者輸入輸出信號(hào)也需要將位寬用parameter參數(shù)化以便更好的調(diào)用等。
舉個(gè)簡(jiǎn)單的小例子:系統(tǒng)頻率100M(周期10ns),假設(shè)需要要求設(shè)計(jì)一個(gè)計(jì)時(shí)器計(jì)時(shí)100ns,那么需要計(jì)數(shù)次數(shù)為:100ns/10ns - 1 = 9,9這個(gè)數(shù)需要用多大位寬的寄存器表示呢?很簡(jiǎn)單,以2為底取對(duì)數(shù)就行,答案是最少4位寬。為了方便地復(fù)用這個(gè)模塊,我們把計(jì)時(shí)時(shí)間參數(shù)化并放到模塊外,如下:
module counter #(
parameter TIME = 'd10 //計(jì)時(shí)時(shí)間,單位10ns
)(
input clk_100M ,
input rst
);
reg [3:0] cnt; //計(jì)數(shù)器
//計(jì)時(shí)器
always@(posedge clk_100M)begin
if(rst)
cnt else if(cnt == TIME - 1)
cnt else
cnt end
endmodule
假設(shè)我們下次設(shè)計(jì)需要一個(gè)計(jì)時(shí)器的話,直接調(diào)用上面的counter模塊并把TIME這個(gè)參數(shù)改成自己需要的參數(shù)就可以,這樣做理論上是可以的,只是會(huì)有一個(gè)致命的隱患。不妨再假設(shè):我現(xiàn)在調(diào)用了counter模塊,并將TIME設(shè)置為20,以實(shí)現(xiàn)計(jì)時(shí)200ns的功能。當(dāng)TIME = 20這個(gè)參數(shù)傳遞到被例化模塊后,可以發(fā)現(xiàn)由于cnt寄存器的位寬僅為4位,其能表示的最大值為4'b1111(即十進(jìn)制下的數(shù)字15),每次其到達(dá)15后就溢出為0重新開始了,也就是說(shuō)這個(gè)200ns的計(jì)時(shí)器實(shí)際上根本就計(jì)數(shù)不到200ns。
這個(gè)隱患發(fā)生的原因就是在設(shè)計(jì)寄存器cnt時(shí)的位寬只有4位,無(wú)法滿足“大量時(shí)間的計(jì)時(shí)任務(wù)”。
2、自己寫一個(gè)Function
現(xiàn)在來(lái)想一下如何解決上述的位寬不匹配的問(wèn)題。將寄存器的位寬設(shè)計(jì)為一個(gè)較大的數(shù)值(如固定為32bit)不失為一個(gè)不錯(cuò)的方法,但是如果將這條規(guī)則適用到每一個(gè)寄存器,則勢(shì)必造成大量的資源浪費(fèi)(你資源多你隨便玩)。而且該方法指標(biāo)不治本,我們需要做的是,這個(gè)寄存器應(yīng)該有多大就設(shè)計(jì)多大的位寬(有多大的腳就穿多大的鞋,鞋子太大一定能穿,但你腳不一定舒服)。
前面說(shuō)過(guò)寄存器的位寬的計(jì)算方法:以2為底取對(duì)數(shù)。所以我們只需要設(shè)計(jì)一個(gè)Function(可綜合),來(lái)實(shí)現(xiàn)此項(xiàng)功能即可。剛好在Xilinx的許多源碼都出現(xiàn)了這個(gè)簡(jiǎn)單的Function,我們直接拿過(guò)來(lái)用就是的:
// function 實(shí)現(xiàn)
function integer clogb2 (input integer bit_depth);
begin
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
bit_depth = bit_depth >> 1;
end
endfunction
// 使用案例
localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1);
reg [C_TRANSACTIONS_NUM : 0] write_index;
reg [C_TRANSACTIONS_NUM : 0] read_index;
上面的代碼就是定義了一個(gè)求位寬的function,用其求得某類寄存器的位寬,然后再對(duì)寄存器賦值時(shí)就直接使用求得的位寬來(lái)賦值,這樣復(fù)用起來(lái)就比較方便了。
我們將這個(gè)代碼放到上面的計(jì)數(shù)器模塊中后,不管需要計(jì)數(shù)多大時(shí)間,都能計(jì)算出相匹配的寄存器位寬了。
3、無(wú)法在輸入輸出端口使用
自己寫Function實(shí)現(xiàn)對(duì)2取對(duì)數(shù)的功能也有一定的局限性:無(wú)法對(duì)輸入輸出端口信號(hào)使用該Function。Function是定義在模塊內(nèi)部,所以若輸入輸出端口也需要根據(jù)輸入的parameter參數(shù)來(lái)以2為底取對(duì)數(shù)的話此種方法就無(wú)能為力了。比如:設(shè)計(jì)一個(gè)同步FIFO,輸出信號(hào)fifo_cnt(計(jì)數(shù)器)是對(duì)寫入FIFO的數(shù)據(jù)進(jìn)行計(jì)數(shù)的寄存器,其最大值即為FIFO的深度DATA_DEPTH ,所以fifo_cnt的位寬就需要在定義模塊輸入輸出端口時(shí)確定,顯然這無(wú)法使用自己構(gòu)造的 cblogb2 Function。那該當(dāng)如何?
//計(jì)數(shù)器法實(shí)現(xiàn)同步FIFO
module sync_fifo_cnt
#(
parameter DATA_WIDTH = 'd8 , //FIFO位寬
parameter DATA_DEPTH = 'd16 //FIFO深度
)
(
input clk , //系統(tǒng)時(shí)鐘
input rst_n , //低電平有效的復(fù)位信號(hào)
input [DATA_WIDTH-1:0] data_in , //寫入的數(shù)據(jù)
input rd_en , //讀使能信號(hào),高電平有效
input wr_en , //寫使能信號(hào),高電平有效
output reg [DATA_WIDTH-1:0] data_out, //輸出的數(shù)據(jù)
output empty , //空標(biāo)志,高電平表示當(dāng)前FIFO已被寫滿
output full , //滿標(biāo)志,高電平表示當(dāng)前FIFO已被讀空
output reg [$clog2(DATA_DEPTH) : 0] fifo_cnt //$clog2是以2為底取對(duì)數(shù)
);
//省略部分代碼
endmodule
4、$clog2系統(tǒng)函數(shù)
其實(shí)辦法也有,在上面的代碼中也展示出來(lái)了,就是使用 $clog2 這個(gè)Verilog的系統(tǒng)函數(shù)。$clog2是Verilog--2005標(biāo)準(zhǔn)新增的一個(gè)系統(tǒng)函數(shù),功能就是對(duì)輸入整數(shù)實(shí)現(xiàn)以2為底取對(duì)數(shù),其結(jié)果向上取整(如5.5取6)。有一點(diǎn)需要說(shuō)明的是,目前Vivado2017以上的版本都是支持這個(gè)系統(tǒng)函數(shù)的(Quartus II不清楚 )。但是百度搜索這條結(jié)果的時(shí)候有兩條結(jié)論是錯(cuò)誤的:
1、Vivado不支持$clog2系統(tǒng)函數(shù)
2、$clog2系統(tǒng)函數(shù)在Vivado實(shí)現(xiàn)的是以e為底取對(duì)數(shù),而不是2
接下來(lái)寫個(gè)簡(jiǎn)單的模塊驗(yàn)證下Vivado對(duì)$clog2系統(tǒng)函數(shù)的支持如何
`timescale 1ns / 1ps
module clog2_test#(
parameter integer num = 325
)
(
input clk,
input rst,
output reg [$clog2(num) - 1:0] result
);
always @(posedge clk)begin
if(rst)
result else
result end
endmodule
可以看到最后編譯出的結(jié)果是9位的,也就說(shuō)明Vivado是支持這個(gè)系統(tǒng)函數(shù)的(版本:2019.2)。
其他變量的位寬設(shè)計(jì)同理。
審核編輯:湯梓紅
-
寄存器
+關(guān)注
關(guān)注
31文章
5357瀏覽量
120580 -
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2256瀏覽量
94679 -
參數(shù)
+關(guān)注
關(guān)注
11文章
1838瀏覽量
32276
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論