J'ai essayé de concevoir et de tester Verilog uniquement avec Python sans écrire Verilog. ** C'est le système que j'ai essayé. ** ** Le test était écrit avant cocotb, le design était Veriloggen ) A été utilisé. L'environnement sera CentOS 6.6.
Pour utiliser Veriloggen, vous devez installer Pyverilog
, Jinja2
selon le [blog] de l'auteur (http://shtaxxx.hatenablog.com/entry/2015/06/22/010559). Je vais.
Comme le système de traitement est écrit en Python 3.3, la compatibilité avec cocotb n'est pas bonne, y compris l'environnement du système d'exploitation.
Par conséquent, dans mon environnement, je l'ai installé directement sans utiliser 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 est le même que précédemment.
Comme la dernière fois, j'ai créé un nouveau répertoire de travail dans le répertoire ʻexample`, créé les répertoires rtl et tests là-bas, et enregistré le DUT et les tests, respectivement. La différence est que le répertoire ** rtl est un fichier Python au lieu d'un fichier Verilog. ** **
├── model
│ └── tests.py
├── rtl
│ └── dff.py
└── tests
├── Makefile
└── run.sh
DUT DUT est le précédent circuit séquentiel de 8 bits. La différence par rapport à l'heure précédente est que la réinitialisation est logique positive et synchrone.
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)
J'ai changé la polarité de réinitialisation de la dernière fois.
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()
Comme il était difficile de les connecter, j'en ai fait un script shell.
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 a généré le code Verilog suivant.
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
Le résultat du test de cocotb est également correct.
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...
Essayons d'impliquer des bus comme Avalon cette fois ...
Recommended Posts