If you’re already using cocotb, you likely have already discovered its ease of use and accessibility in verification tasks. It proves particularly helpful when setting VHDL generics, and here’s how you can take advantage of that capability.
As mentioned in the previous post, “Install Cocotb on Windows 10 to Boost FPGA Verification Productivity,” cocotb is a testbench environment for verifying RTL code using Python. The open source verification framework provides several advantages over the current mainstream ASIC and FPGA verification methodologies of SystemVerilog and UVM, among those being the abilities to edit and rerun test cases without recompiling RTL code, abstract RTL simulator interaction, and reduce overhead in testbench creation.
As a hypothetical case, suppose you have a module with a generic whose value you wish to update for simulation. Generic values allow static parameters like timing and size data to be sent from one architecture in a design unit, but apply to the whole of the DU.
Now, how can you update them using cocotb?
Let’s start by using the adder example provided in the git repo for cocotb.
-- Adder DUT
library ieee ;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
generic(
DATA_WIDTH : positive := 4);
port(
A : in unsigned(DATA_WIDTH-1 downto 0);
B : in unsigned(DATA_WIDTH-1 downto 0);
X : out unsigned(DATA_WIDTH downto 0)
);
end adder;
architecture RTL of adder is
begin
process(A, B)
begin
X <= resize(A, X'length) + B;
end process;
end RTL;
In order to change the generic DATA_WIDTH , you can pass the GENERICS variable to make.
make SIM=questa GUI=1 TOPLEVEL_LANG=vhdl GENERICS="DATA_WIDTH=10"
When QuestaSim opens up, the value for DATA_WIDTH should be 10. The signals A and B should be 10 bits wide. The signal X should be 11 bits wide.
The value for DATA_WIDTH can be used in cocotb tests. Add a new test to test_adder.py.
@cocotb.test()
def adder_big_test(dut):
"""Test for adding 2 numbers to maximize DATA_WIDTH"""
yield Timer(2)
data_width = dut.DATA_WIDTH.value
max_val = 2**data_width - 1
A = max_val
B = max_val
dut.A = A
dut.B = B
yield Timer(2)
if int(dut.X) != adder_model(A, B):
raise TestFailure(
"Adder result is incorrect: %s + %s = %s" %
(int(dut.A), int(dut.B), int(dut.X)))
else: # these last two lines are not strictly necessary
dut._log.info("Ok!")
The value of DATA_WIDTH is read by dut.DATA_WIDTH.value . With DATA_WIDTH set to 10, max_val should take on the value of 0x3FF. When QuestaSim runs test_adder.adder_big_test , signals A and B should be set to 0x3FF. The signal X should compute a value of 0x7FE.
Updating VHDL generics and using generic in tests is painless once you know cocotb’s method for setting and using those values.
Additional information on cocotb can be found on the project’s GitHub page found at https://github.com/potentialventures/cocotb. There, you can read more documentation, raise a bug, request feature enhancements, join the mailing list, email the developers, or follow the project on Twitter.
By Juan Morales