I tried to design and test Verilog only with Python without writing Verilog. ** This is the system I tried. ** ** The test was written before cocotb, the design was Veriloggen ) Was used. The environment will be CentOS 6.6.
To use Veriloggen, you need to install Pyverilog
, Jinja2
as per the author's blog. I will.
Since the processing system is written in Python 3.3, compatibility with cocotb is not good, including the OS environment.
Therefore, in my environment, I installed it directly without using virtualenv
.
git clone https://github.com/shtaxxx/Pyverilog
git clone https://github.com/shtaxxx/veriloggen
sudo pip install jinja2
cd Pyverilog
sudo python3 setup.py install
cd ../veriloggen
sudo python3 setup.py install
cd ../
cocotb is the same as previously.
This time as well, I created a new working directory in the ʻexample` directory, created rtl and tests directories there, and saved the DUT and tests, respectively. The difference is that I made the ** rtl directory a Python file instead of a Verilog file. ** **
├── model
│ └── tests.py
├── rtl
│ └── dff.py
└── tests
├── Makefile
└── run.sh
DUT DUT is the previous 8-bit sequential circuit. The difference from the previous time is that the reset is positive logic and synchronous.
dff.py
import sys, os
from veriloggen import *
def mkdff():
m = Module('dff')
width = m.Parameter('WIDTH', 8)
clk = m.Input('CLK')
rst = m.Input('RST')
d = m.Input('D', width)
q = m.OutputReg('Q', width)
m.Always(Posedge(clk))(
If(rst)(
q(0)
).Else(
q(d)
))
return m
if __name__ == '__main__':
dff = mkdff()
verilog = dff.to_verilog()
print(verilog)
I changed the reset polarity from the last time.
tests.py
import cocotb
from cocotb.triggers import Timer, RisingEdge
from cocotb.result import TestFailure
from cocotb.clock import Clock
import random
class DffTB(object):
def __init__(self, dut, dubug=True):
self.dut = dut
@cocotb.coroutine
def reset(self, duration=10000):
self.dut.log.info("Resetting DUT")
self.dut.RST <= 1
self.dut.D <= 0
yield Timer(duration)
yield RisingEdge(self.dut.CLK)
self.dut.RST <= 0
self.dut.log.info("Out of reset")
@cocotb.coroutine
def gen_and_check(self):
D = random.randint(0, 255)
self.dut.D = D;
yield RisingEdge(self.dut.CLK)
yield Timer(1)
if int(self.dut.Q) != D :
raise TestFailure(
"[NG] Compre error. D==%s Q==%s" % (D, int(self.dut.Q)))
else :
self.dut.log.info("[OK]")
@cocotb.coroutine
def clock_gen(signal):
while True:
signal <= 0
yield Timer(5000)
signal <= 1
yield Timer(5000)
@cocotb.test()
def basic_test(dut):
"""basic_test"""
tb = DffTB(dut)
cocotb.fork(clock_gen(dut.CLK))
yield RisingEdge(dut.CLK)
yield tb.reset()
for i in range(30):
yield tb.gen_and_check()
Since it was troublesome to connect them, I made it a shell script.
run.sh
#!/bin/bash
RTLPATH=../rtl
if [ -e ${RTLPATH}/dff.v ]; then
rm ${RTLPATH}/dff.v
fi
python3 ${RTLPATH}/dff.py > ${RTLPATH}/dff.v
make
Veriloggen generated the following Verilog code.
dff.v
module dff #
(
parameter WIDTH = 8
)
(
input [0:0] CLK,
input [0:0] RST,
input [(WIDTH - 1):0] D,
output reg [(WIDTH - 1):0] Q
);
always @(posedge CLK)
begin
if(RST) begin
Q <= 0;
end
else begin
Q <= D;
end
end
endmodule
The test result by cocotb is also okay.
TESTCASE= TOPLEVEL=dff \
vvp -M /tmp/cocotb/build/libs/x86_64 -m gpivpi sim_build/sim.vvp
-.--ns INFO cocotb.gpi GpiCommon.cpp:47 in gpi_print_registered_impl VPI registered
0.00ns INFO cocotb.gpi gpi_embed.c:229 in embed_sim_init Running on Icarus Verilog version 0.9.6
0.00ns INFO cocotb.gpi gpi_embed.c:230 in embed_sim_init Python interpreter initialised and cocotb loaded!
0.00ns INFO cocotb.gpi __init__.py:103 in _initialise_testbench Running tests with Cocotb v1.0 from /tmp/cocotb
0.00ns INFO cocotb.gpi __init__.py:119 in _initialise_testbench Seeding Python random module with 1437305945
0.00ns INFO cocotb.regression regression.py:153 in initialise Found test tests.basic_test
0.00ns INFO cocotb.regression regression.py:254 in execute Running test 1/1: basic_test
0.00ns INFO ..tb.coroutine.basic_test.0x2353ed0 decorators.py:186 in send Starting test: "basic_test"
Description: basic_test
5.00ns INFO cocotb.dff tests.py:14 in reset Resetting DUT
15.00ns INFO cocotb.dff tests.py:20 in reset Out of reset
25.00ns INFO cocotb.dff tests.py:32 in gen_and_check [OK]
35.00ns INFO cocotb.dff tests.py:32 in gen_and_check [OK]
(Omission)
295.00ns INFO cocotb.dff tests.py:32 in gen_and_check [OK]
305.00ns INFO cocotb.dff tests.py:32 in gen_and_check [OK]
315.00ns INFO cocotb.dff tests.py:32 in gen_and_check [OK]
315.00ns INFO cocotb.regression regression.py:201 in handle_result Test Passed: basic_test
315.00ns INFO cocotb.regression regression.py:162 in tear_down Passed 1 tests (0 skipped)
315.00ns INFO cocotb.regression regression.py:168 in tear_down Shutting down...
Let's try it with a bus such as Avalon this time ...
Recommended Posts