Skip to content

Commit e998445

Browse files
committed
add testbenches for the rest of verilog-language/basics hdl
1 parent 9c0930d commit e998445

File tree

15 files changed

+734
-4
lines changed

15 files changed

+734
-4
lines changed

problems/verilog-language/basics/7458-chip/rtl/7458.v renamed to problems/verilog-language/basics/7458-chip/rtl/c7458.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
`timescale 1ns / 1ps
33
`default_nettype none
44

5-
module 7458 (
5+
module c7458 (
66
input wire p1a,
77
input wire p1b,
88
input wire p1c,
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import logging
2+
from cocotb.clock import Timer
3+
4+
5+
class DataError(Exception):
6+
pass
7+
8+
9+
class TB:
10+
def __init__(self, dut):
11+
self.dut = dut
12+
13+
# Start logging
14+
self.log = logging.getLogger("cocotb.tb")
15+
self.log.setLevel(logging.DEBUG)
16+
17+
# Simulation Signals
18+
self.get_signals()
19+
20+
# Zero out signals
21+
self.zero_signals()
22+
23+
def get_signals(self):
24+
self.p1a = self.dut.p1a
25+
self.p1b = self.dut.p1b
26+
self.p1c = self.dut.p1c
27+
self.p1d = self.dut.p1d
28+
self.p1e = self.dut.p1e
29+
self.p1f = self.dut.p1f
30+
self.p1y = self.dut.p1y
31+
32+
self.p2a = self.dut.p2a
33+
self.p2b = self.dut.p2b
34+
self.p2c = self.dut.p2c
35+
self.p2d = self.dut.p2d
36+
self.p2y = self.dut.p2y
37+
38+
def zero_signals(self):
39+
self.p1a.value = 0
40+
self.p1b.value = 0
41+
self.p1c.value = 0
42+
self.p1d.value = 0
43+
self.p1e.value = 0
44+
self.p1f.value = 0
45+
46+
self.p2a.value = 0
47+
self.p2b.value = 0
48+
self.p2c.value = 0
49+
self.p2d.value = 0
50+
51+
async def set_p1_input_val(self, val):
52+
self.p1a.value = val[0]
53+
self.p1b.value = val[1]
54+
self.p1c.value = val[2]
55+
self.p1d.value = val[3]
56+
self.p1e.value = val[4]
57+
self.p1f.value = val[5]
58+
await Timer(1, units="ns")
59+
60+
async def p1_logic_check(self):
61+
await Timer(1, units="ns")
62+
if (
63+
(bool(self.p1a.value) and bool(self.p1b.value) and bool(self.p1c.value))
64+
or (bool(self.p1d.value) and bool(self.p1e.value) and bool(self.p1f.value))
65+
) != bool(self.p1y.value):
66+
raise DataError(
67+
f"(p1a && p1b && p1c) || (p1d && p1e && p1f) should be p1y, but ({self.p1a.value} && {self.p1b.value} && {self.p1c.value}) || ({self.p1d.value} && {self.p1e.value} && {self.p1f.value}) != {self.p1y.value}."
68+
)
69+
70+
async def set_p2_input_val(self, val):
71+
self.p2a.value = val[0]
72+
self.p2b.value = val[1]
73+
self.p2c.value = val[2]
74+
self.p2d.value = val[3]
75+
await Timer(1, units="ns")
76+
77+
async def p2_logic_check(self):
78+
await Timer(1, units="ns")
79+
if (
80+
(bool(self.p2a.value) and bool(self.p2b.value))
81+
or (bool(self.p2d.value) and bool(self.p2e.value))
82+
) != bool(self.p2y.value):
83+
raise DataError(
84+
f"(p2a && p2b) || (p2c && p2d) should be p2y, but ({self.p2a.value} && {self.p2b.value}) || ({self.p2c.value} && {self.p2d.value}) != {self.p2y.value}."
85+
)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import os
2+
import pytest
3+
4+
import cocotb
5+
from cocotb.regression import TestFactory
6+
from cocotb_test.simulator import run
7+
8+
from c7458 import TB
9+
10+
11+
async def p1_logic_check(dut):
12+
tb = TB(dut)
13+
14+
test_vals = [
15+
[0, 0, 0, 0, 0, 0],
16+
[0, 1, 0, 0, 1, 0],
17+
[0, 0, 0, 1, 1, 1],
18+
[1, 1, 0, 1, 0, 1],
19+
[1, 1, 1, 1, 1, 1],
20+
]
21+
22+
tb.log.info("Checking output value...")
23+
24+
for i in range(len(test_vals)):
25+
tb.set_p1_input_val(test_vals[i])
26+
tb.p1_logic_check()
27+
28+
29+
async def p2_logic_check(dut):
30+
tb = TB(dut)
31+
32+
test_vals = [
33+
[0, 0, 0, 0],
34+
[0, 1, 0, 0],
35+
[0, 0, 0, 1],
36+
[1, 1, 1, 1],
37+
]
38+
39+
tb.log.info("Checking output value...")
40+
41+
for i in range(len(test_vals)):
42+
tb.set_p2_input_val(test_vals[i])
43+
tb.p2_logic_check()
44+
45+
46+
if cocotb.SIM_NAME:
47+
test1 = TestFactory(p1_logic_check)
48+
test1.generate_tests()
49+
test2 = TestFactory(p2_logic_check)
50+
test2.generate_tests()
51+
52+
# cocotb-test
53+
54+
tests_dir = os.path.abspath(os.path.dirname(__file__))
55+
rtl_dir = os.path.abspath(os.path.join(tests_dir, "..", "rtl"))
56+
57+
parameter_list = [{}]
58+
59+
60+
@pytest.mark.parametrize("parameters", parameter_list)
61+
def test_constant_zero(request, parameters):
62+
dut = "c7458"
63+
module = os.path.splitext(os.path.basename(__file__))[0]
64+
toplevel = dut
65+
66+
verilog_sources = [
67+
os.path.join(rtl_dir, f"{dut}.v"),
68+
]
69+
70+
extra_env = {f"PARAM_{k}": str(v) for k, v in parameters.items()}
71+
72+
sim_build = os.path.join(
73+
tests_dir, "sim_build", request.node.name.replace("[", "-").replace("]", "")
74+
)
75+
76+
run(
77+
python_search=[tests_dir],
78+
verilog_sources=verilog_sources,
79+
toplevel=toplevel,
80+
module=module,
81+
parameters=parameters,
82+
sim_build=sim_build,
83+
extra_env=extra_env,
84+
compile_args=["--timing", "-O3"],
85+
waves=True,
86+
)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import logging
2+
from cocotb.clock import Timer
3+
4+
5+
class DataError(Exception):
6+
pass
7+
8+
9+
class TB:
10+
def __init__(self, dut):
11+
self.dut = dut
12+
13+
# Start logging
14+
self.log = logging.getLogger("cocotb.tb")
15+
self.log.setLevel(logging.DEBUG)
16+
17+
# Simulation Signals
18+
self.get_signals()
19+
20+
# Zero out signals
21+
self.zero_signals()
22+
23+
def get_signals(self):
24+
self.a = self.dut.a
25+
self.b = self.dut.b
26+
27+
self.out = self.dut.out
28+
29+
def zero_signals(self):
30+
self.a.value = 0
31+
self.b.value = 0
32+
33+
async def set_input_val(self, val):
34+
self.a.value = val[0]
35+
self.b.value = val[1]
36+
await Timer(1, units="ns")
37+
38+
async def logic_check(self):
39+
await Timer(1, units="ns")
40+
if (bool(self.a.value) and bool(self.b.value)) != bool(self.out.value):
41+
raise DataError(
42+
f"a && b should be output, but ({self.a.value} && {self.b.value}) != {self.out.value}."
43+
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import os
2+
import pytest
3+
4+
import cocotb
5+
from cocotb.regression import TestFactory
6+
from cocotb_test.simulator import run
7+
8+
from and_gate import TB
9+
10+
11+
async def output_logic_check(dut):
12+
tb = TB(dut)
13+
14+
test_vals = [
15+
[0, 0],
16+
[1, 0],
17+
[0, 1],
18+
[1, 1],
19+
]
20+
21+
tb.log.info("Checking output value...")
22+
23+
for i in range(len(test_vals)):
24+
tb.set_input_val(test_vals[i])
25+
tb.logic_check()
26+
27+
28+
if cocotb.SIM_NAME:
29+
test1 = TestFactory(output_logic_check)
30+
test1.generate_tests()
31+
32+
# cocotb-test
33+
34+
tests_dir = os.path.abspath(os.path.dirname(__file__))
35+
rtl_dir = os.path.abspath(os.path.join(tests_dir, "..", "rtl"))
36+
37+
parameter_list = [{}]
38+
39+
40+
@pytest.mark.parametrize("parameters", parameter_list)
41+
def test_constant_zero(request, parameters):
42+
dut = "and_gate"
43+
module = os.path.splitext(os.path.basename(__file__))[0]
44+
toplevel = dut
45+
46+
verilog_sources = [
47+
os.path.join(rtl_dir, f"{dut}.v"),
48+
]
49+
50+
extra_env = {f"PARAM_{k}": str(v) for k, v in parameters.items()}
51+
52+
sim_build = os.path.join(
53+
tests_dir, "sim_build", request.node.name.replace("[", "-").replace("]", "")
54+
)
55+
56+
run(
57+
python_search=[tests_dir],
58+
verilog_sources=verilog_sources,
59+
toplevel=toplevel,
60+
module=module,
61+
parameters=parameters,
62+
sim_build=sim_build,
63+
extra_env=extra_env,
64+
compile_args=["--timing", "-O3"],
65+
waves=True,
66+
)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import logging
2+
from cocotb.clock import Timer
3+
4+
5+
class DataError(Exception):
6+
pass
7+
8+
9+
class TB:
10+
def __init__(self, dut):
11+
self.dut = dut
12+
13+
# Start logging
14+
self.log = logging.getLogger("cocotb.tb")
15+
self.log.setLevel(logging.DEBUG)
16+
17+
# Simulation Signals
18+
self.get_signals()
19+
20+
# Zero out signals
21+
self.zero_signals()
22+
23+
def get_signals(self):
24+
self.a = self.dut.a
25+
self.b = self.dut.b
26+
self.c = self.dut.c
27+
self.d = self.dut.d
28+
29+
self.out = self.dut.out
30+
self.out_n = self.dut.out_n
31+
32+
def zero_signals(self):
33+
self.a.value = 0
34+
self.b.value = 0
35+
self.c.value = 0
36+
self.d.value = 0
37+
38+
async def set_input_val(self, val):
39+
self.a.value = val[0]
40+
self.b.value = val[1]
41+
self.c.value = val[2]
42+
self.d.value = val[3]
43+
await Timer(1, units="ns")
44+
45+
async def logic_check(self):
46+
await Timer(1, units="ns")
47+
if (
48+
(bool(self.a.value) and bool(self.b.value))
49+
or (bool(self.c.value) and bool(self.d.value))
50+
) != bool(self.out):
51+
raise DataError(
52+
f"out should be (a && b) || (c && d), but ({self.a.value} && {self.b.value}) || ({self.c.value} && {self.d.value})"
53+
)
54+
if int(self.out.value) == int(self.out_n.value):
55+
raise DataError(
56+
f"out_n should be inverse of out, but {self.out.value} == {self.out_n.value}."
57+
)

0 commit comments

Comments
 (0)