在上一篇文章里我們嘗試了第二種在靜態(tài)模塊中構(gòu)建可控隨機(jī)的方案,接下來我們延續(xù)這個(gè)思路,來嘗試編寫一個(gè)能夠模擬亞穩(wěn)態(tài)隨機(jī)恢復(fù)的單比特信號(hào)同步器,那么開始逐一的拆解并解決問題吧。要聲明一下,下面的代碼只是個(gè)人探究并沒有在實(shí)際工程中實(shí)踐過,因此難免有錯(cuò)誤和漏洞。接口module名為bit_async,既然是單比特的同步器那么接口自然就是6根線,分別以i_*和o_*來標(biāo)記時(shí)鐘域:
module bit_async #(
//parameter
)( /*AUTOARG*/
// Outputs
o_data,
// Inputs
i_clk, i_rst_n, i_data, o_clk, o_rst_n
);
// ----------------------------------------------------------------
// Interface declare
// ----------------------------------------------------------------
input i_clk;
input i_rst_n;
input i_data;
input o_clk;
input o_rst_n;
output o_data;可控隨機(jī)第一步自然是做用來產(chǎn)生隨機(jī)數(shù)的function,思路就是另一篇博客中說的方式,通過%m來差異化每一個(gè)inst隨機(jī)時(shí)的urandom的種子,思路已經(jīng)在上一篇文章中說明了。將宏定義定義在tb.f最前面的define文件中:
`define module_urandom_define \
string path_str; \
initial path_str = $psprintf(path_str, "%m"); \
\
function integer urandom; \
integer seed, i; \
begin \
seed = $urandom(); \
for(i=path_str.len; i>=0; i=i-1)begin \
seed = seed ^ path_str.getc(i); \
seed = $urandom(seed); \
end \
urandom = $abs(seed); \
end \
endfunction \
function integer urandom_range(); \
input integer min, max; \
integer seed, i; \
begin \
seed = $urandom(); \
for(i=path_str.len; i>=0; i=i-1)begin \
seed = seed ^ path_str.getc(i); \
seed = $urandom(seed); \
end \
urandom_range = min + $abs(seed % (max - min)); \
end \
endfunction而后在bit_async中引用宏定義:// ----------------------------------------------------------------
// Wire declare
// ----------------------------------------------------------------
`module_urandom_define就可以正常的使用urandom()和urandom_range()兩個(gè)函數(shù)了。跳變檢查因?yàn)橹挥性谳斎胄盘?hào)發(fā)生跳變時(shí)才會(huì)涉及到亞穩(wěn)態(tài)和亞穩(wěn)態(tài)的隨機(jī)恢復(fù)問題,所以需要識(shí)別信號(hào)跳變,在代碼里我做了信號(hào)i_data_hold和i_data_jump,i_data_jump是i_data_hold取反的結(jié)果,所以只需關(guān)注i_data_hold的邏輯就可以。
最簡(jiǎn)單的思路,在i_clk時(shí)鐘前后兩拍的值一樣,就可以認(rèn)為輸入信號(hào)是穩(wěn)定的:
reg i_data_i_ff;
always @(posedge i_clk or negedge i_rst_n) begin
if(i_rst_n == 1'b0)begin
i_data_i_ff 但是這樣存在一個(gè)問題,即在慢打快的時(shí)候接受域的快時(shí)鐘會(huì)在多拍都看到信號(hào)跳轉(zhuǎn),比如下面這樣:
但是我們知道在信號(hào)進(jìn)行跨時(shí)鐘域同步時(shí)必須遵循寄存器輸出以及走線在快時(shí)鐘域一拍以內(nèi),因此不會(huì)出現(xiàn)一次跳變的信號(hào)在采樣時(shí)連續(xù)多拍都是不穩(wěn)定的信號(hào)。所以基于這個(gè)思路,我補(bǔ)充了一個(gè)條件,也就是說在o_clk下i_data如果連續(xù)兩拍數(shù)值一致,那么也認(rèn)為其保持不會(huì)產(chǎn)生亞穩(wěn)態(tài),這樣等價(jià)于在快時(shí)鐘下兩拍一致就可以:
// ----------------------------------------------------------------
// gain jump point
// ----------------------------------------------------------------
reg i_data_i_ff;
always @(posedge i_clk or negedge i_rst_n) begin
if(i_rst_n == 1'b0)begin
i_data_i_ff 亞穩(wěn)態(tài)恢復(fù)因?yàn)榕袛嗵兪窃趇_data輸入時(shí)進(jìn)行判斷的,所以亞穩(wěn)態(tài)隨機(jī)恢復(fù)的事情也是在o_clk打拍的第一拍來進(jìn)行的。簡(jiǎn)單來說就是在打拍時(shí)判斷是否為i_data_jump狀態(tài),如果是則進(jìn)行隨機(jī)恢復(fù):
// ----------------------------------------------------------------
// i_data -> o_data_ff1 -> o_data_ff2
// ----------------------------------------------------------------
reg o_data_ff1, o_data_ff2;
always @(posedge o_clk or negedge o_rst_n) begin
if(o_rst_n == 1'b0)begin
o_data_ff1 = 5)begin
o_data_ff1 信號(hào)輸出嚴(yán)格來說,模塊應(yīng)該做成拍數(shù)可配置的,不過因?yàn)橹皇且粋(gè)探索所以我就固定做成打兩拍了:
always @(posedge o_clk or negedge o_rst_n) begin
if(o_rst_n == 1'b0)begin
o_data_ff2 如此一來,單比特的跨時(shí)鐘域同步器就完成了。波形仿真嘗試仿真一下波形,在testbench里例化了4個(gè)bit_async,然后把o_data_ff1都拽出來看看。先是慢打快的場(chǎng)景:
以及快打慢的場(chǎng)景:
系列文章入口——
【芯片設(shè)計(jì)】SoC 101(一):緒論 | 【芯片設(shè)計(jì)】FIFO漫談(零)從無處不在的FIFO開始說起 | 【芯片設(shè)計(jì)】計(jì)算機(jī)體系結(jié)構(gòu)(一)虛擬內(nèi)存 | 【芯片設(shè)計(jì)】深入理解AMBA總線(零)緒論
| 【芯片設(shè)計(jì)】握手協(xié)議的介紹與時(shí)序說明 | 【芯片設(shè)計(jì)】復(fù)位那些小事 —— 復(fù)位消抖 | 【芯片設(shè)計(jì)】快速入門數(shù)字芯片設(shè)計(jì)(一)Introduction | 【芯片驗(yàn)證】UVM源碼計(jì)劃(零)下定決心讀源碼前的自測(cè)環(huán)節(jié)
| 【芯片設(shè)計(jì)】異步電路碎碎念(一) 到底什么是異步電路
| 【芯片設(shè)計(jì)】從RTL到GDS(一):Introduction
| 其他文章鏈接——
【芯片驗(yàn)證】sva_assertion: 15道助力飛升的斷言練習(xí) | 【芯片驗(yàn)證】可能是RTL定向驗(yàn)證的巔峰之作 | 【芯片驗(yàn)證】RTL仿真中X態(tài)行為的傳播 —— 從xprop說起 | 【芯片驗(yàn)證】年輕人的第一個(gè)systemVerilog驗(yàn)證環(huán)境全工程與解析 |
【芯片設(shè)計(jì)】verilog中有符號(hào)數(shù)和無符號(hào)數(shù)的本質(zhì)探究
| 【芯片設(shè)計(jì)】論RTL中always語(yǔ)法的消失術(shù) | 【芯片設(shè)計(jì)】代碼即注釋,注釋即代碼 | 【芯片設(shè)計(jì)】700行代碼的risc處理器你確實(shí)不能要求太多了 |
入職芯片開發(fā)部門后,每天摸魚之外的時(shí)間我們要做些什么呢 | 如何計(jì)算系統(tǒng)的outstanding 和 burst length? | 芯片搬磚日常·逼死強(qiáng)迫癥的關(guān)鍵詞不對(duì)齊事件 | 熟人社會(huì)里,一群沒有社會(huì)價(jià)值的局外人 |
|