cocotb的出現(xiàn)使得我們能夠在做RTL仿真驗證時依托Python來進行測試用例的構建,當我們習慣了用Verilog、SystemVerilog來構建測試用例時,切換到cocotb后最直觀的方式便是我們能夠建立cocotb中的基礎語法與SystemVerilog中仿真常用的關鍵字又一個對應,能夠使我們又一個初步的對照。本篇就cocotb中的基礎語法與SystemVerilog中的常用語法做一個對照總結。
非阻塞賦值
在使用Systemverilog進行仿真時,對于接口信號,往往建議采用非阻塞賦值進行操作,其符號為“<=”.
在cocotb中,對于信號的賦值,其提供相應的非阻塞賦值方式,其符號也同樣為“<=”。
在cocotb的手冊里提到:
The syntaxsig<=?new_value?is a short form of?sig.value?=?new_value. It not only resembles HDL syntax, but also has the same semantics: writes are not applied immediately, but delayed until the next write cycle.
因而我們可以在cocotb中這樣來進行非阻塞賦值:
# Get a reference to the "clk" signal and assign a valueclk = dut.clkclk.value = 1 # Direct assignment through the hierarchydut.input_signal <= 12 # Assign a value to a memory deep in the hierarchydut.sub_block.memory.array[4] <= 2
阻塞賦值
針對阻塞賦值(立即生效),cocotb提供了相應的語法:
setimmediatevalue(value)
因而對于阻塞賦值,我們在cocotb中可以這樣寫:
dut.input_signal.setimmediatevalue(1)
信號值讀取
對于信號的讀取,我們在SystemVerilog中,可以直接讀取信號值,而在cocotb中,其為接口變量提供了value方法屬性用于獲取信號值。
讀取方式:sig.value
返回類型:BinaryValue
Accessing thevalueproperty of a handle object will return aBinaryValueobject. Any unresolved bits are preserved and can be accessed using thebinstrattribute, or a resolved integer value can be accessed using theintegerattribute.
信號的讀取我們可以這么來寫:
# Read a value back from the DUTcount=dut.counter.valueprint(count.binstr)1X1010# Resolve the value to an integer (X or Z treated as 0)print(count.integer)42# Show number of bits in a valueprint(count.n_bits)6
#Time
在仿真里延遲等待是經(jīng)常遇到的,在cocotb里,我們通過Timer來實現(xiàn)延遲:
cocotb.triggers.Timer(time_ps,units=None)
Parameters
time_ps (numbers.Real or decimal.Decimal) – The time value. Note that despite the name this is not actually in picoseconds but depends on the units argument.
units (str or None, optional) – One of None, 'fs', 'ps', 'ns', 'us', 'ms', 'sec'. When no units is given (None) the timestep is determined by the simulator.
由于cocotb是基于協(xié)程的,而延遲函數(shù)的執(zhí)行的時間長度是依賴于仿真器的,因此Timer延遲的執(zhí)行需調(diào)用await:
await Timer(1, units='ns')
邊沿檢測
在SystemVerilog中我們常用posedge、negedge來檢測上升沿和下降沿,在cocotb里,針對邊沿檢測,其提供了四個調(diào)用:
等待調(diào)變
class cocotb.triggers.Edge(*args, **kwargs)
Fires on any value change of signal.
等待上升沿
class cocotb.triggers.RisingEdge(*args, **kwargs)
Fires on the rising edge of signal, on a transition from 0 to 1.
等待下降沿
class cocotb.triggers.FallingEdge(*args, **kwargs)
Fires on the falling edge of signal, on a transition from 1 to 0.
檢測等待指定到個數(shù)邊沿
class cocotb.triggers.ClockCycles(signal,num_cycles,rising=True)
Fires after num_cycles transitions of signal from 0 to 1.
Parameters
signal – The signal to monitor.
num_cycles (int) – The number of cycles to count.
rising (bool, optional) – If True, the default, count rising edges. Otherwise, count falling edges.
我們在使用時,可以這么來寫:
#等待信號signalA發(fā)生變化await cocotb.triggers.Edge(dut.signalA)#等待signalA從0變?yōu)?await cocotb.triggers.RisingEdge(dut.signalA)#等待signalA從1變?yōu)?await cocotb.triggers.FallingEdge(dut.signalA)#等待signalA從0變?yōu)?三次awaitcocotb.triggers.ClockCycles(dut.signalA,3,true)
fork-join_none
SystemVerilog中的fork-join_none用于發(fā)起一個線程但不等待線程的結束,在cocotb中,相應的語法為fork:
cocotb.fork()
Schedule a coroutine to be run concurrently
在寫仿真代碼時,我們可以這么寫:
async def reset_dut(reset_n, duration_ns): reset_n <= 0 await Timer(duration_ns, units='ns') reset_n <= 1 reset_n._log.debug("Reset complete")reset_thread = cocotb.fork(reset_dut(reset_n, duration_ns=500))
這里值得注意的是,由于fork是起一個協(xié)程,因而resut_dut需添加async聲明。
fork-join
與SystemVerilog中相對應的,cocotb等待一個協(xié)程的結束同樣提供了join方法:
class cocotb.triggers.Join(*args, **kwargs)
Fires when a fork()ed coroutine completes.
The result of blocking on the trigger can be used to get the coroutine result:
使用方式:
async def coro_inner(): await Timer(1, units='ns') return "Hello world" task = cocotb.fork(coro_inner())result = await Join(task)assert result == "Hello world"
fork-any
相較于SystemVerilog中的join-any語法,cocotb并無專門的對應語法,但卻有相似的方法供調(diào)用:
class cocotb.triggers.First(*triggers)
等待第一個協(xié)程結束即返回
t1 = Timer(10, units='ps')t2 = Timer(11, units='ps')t_ret = await First(t1, t2)
這里我們通過First等待t1、t2第一個返回的結果后await結束,并將第一個返回的協(xié)程的返回結果賦值給t_ret。
event
對于SystemVerilog中的event,在cocotb中同樣提供類似的event:
class cocotb.triggers.Event(name=None)
用于兩個協(xié)程間的同步
方法:
set(data=None):喚醒所有等待該事件的協(xié)程
wait(): 等待事件的出發(fā)(await),如果事件已經(jīng)觸發(fā),立即返回
clear(): 清楚以觸發(fā)的事件
is_set():判斷事件是否觸發(fā)
旗語
cocotb中提供了Lock操作用來實現(xiàn)與SystemVerilog中相似的操作,不過Lock不可聲明旗語為多個:
class cocotb.triggers.Lock(name=None)
方法:
locked : True if the lock is held.
acquire():Produce a trigger which fires when the lock is acquired.
release(): Release the lock.
mailbox
SystemVerilog中的mailbox主要用于不同進程間的通信,在cocotb中,普通的Python的隊列即可實現(xiàn)該功能(協(xié)程中無需沒有進程間同步問題)。
審核編輯 :李倩
-
代碼
+關注
關注
30文章
4788瀏覽量
68612 -
語法
+關注
關注
0文章
44瀏覽量
9812 -
非阻塞賦值
+關注
關注
0文章
10瀏覽量
10001
原文標題:cocotb—基礎語法對照篇
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論