6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Veriloggenとcocotbで、PythonのみでVerilogのデザイン・テストを行う。

Posted at

##はじめに
Verilog書かずにPythonのみでVerilogのデザイン・テストをやってみました。やってみた系です。
テストは以前書いたcocotb、デザインにはVeriloggenを使用しました。
環境はCentOS6.6になります。

##環境構築
Veriloggenを使用するには、作者さんのブログの通り、Pyverilog, Jinja2のインストールが必要になります。
処理系がPython3.3で書かれているため、cocotbとの相性がOS環境も含めて今ひとつよくありません。
よって、ウチの環境では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は、以前と同じです。

今回も前回と同様、exampleディレクトリに新たにワークディレクトリを作成し、そこにrtlおよびtestsディレクトリを作成し、それぞれDUT、テストを保存しました。
違いは、rtlディレクトリにVerilogファイルではなくPythonファイルにしたことです。

├── model
│   └── tests.py
├── rtl
│   └── dff.py
└── tests
    ├── Makefile
    └── run.sh

##DUT
DUTは前回の8bit順序回路になります。リセットが正論理かつ同期になったのが前回との違いです。

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)

##テスト
リセット極性を前回から変えてみました。

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()

##実行スクリプト
つなぎ合わせるのが面倒だったのでシェルスクリプトにしました。

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では以下のようなVerilogコードが生成されました。

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

cocotbによるテスト結果も無事にオッケーです。

        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]

(中略)

   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...

##おわりに
今度はAvalonなどのバスを絡めてやってみましょうかねえ…。

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?