forked from tanchou/Verilog
struct
This commit is contained in:
4
Help/presentation_examples/blink/.gitignore
vendored
Normal file
4
Help/presentation_examples/blink/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
runs
|
||||
.vscode
|
||||
workspace.code-workspace
|
||||
*.pyc
|
@@ -0,0 +1,4 @@
|
||||
IO_LOC "led" 15;
|
||||
IO_PORT "led" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
|
||||
IO_LOC "clk" 4;
|
||||
IO_PORT "clk" PULL_MODE=UP BANK_VCCIO=1.8;
|
2
Help/presentation_examples/blink/project.bat
Normal file
2
Help/presentation_examples/blink/project.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@call c:\tools\oss-cad-suite\environment.bat
|
||||
@tclsh scripts\project.tcl %*
|
@@ -0,0 +1,20 @@
|
||||
puts "Starting TCL script"
|
||||
#set path test1b_tb
|
||||
#gtkwave::forceOpenTreeNode $path
|
||||
set nfacs [ gtkwave::getNumFacs ]
|
||||
puts "There are $nfacs signals"
|
||||
set l [list]
|
||||
|
||||
for {set i 0} {$i < $nfacs } {incr i} {
|
||||
set facname [ gtkwave::getFacName $i ]
|
||||
set numdots [ expr {[llength [split $facname .]] - 1}]
|
||||
# puts "$numdots"
|
||||
if {$numdots == 1} {
|
||||
lappend l "$facname"
|
||||
puts "Added signal $facname"
|
||||
}
|
||||
}
|
||||
|
||||
set num_added [ gtkwave::addSignalsFromList $l ]
|
||||
gtkwave::setZoomRangeTimes [ gtkwave::getMinTime ] [ gtkwave::getMaxTime ]
|
||||
puts "Start time [ gtkwave::getMinTime ] end time: [ gtkwave::getMaxTime ]"
|
184
Help/presentation_examples/blink/scripts/project.tcl
Normal file
184
Help/presentation_examples/blink/scripts/project.tcl
Normal file
@@ -0,0 +1,184 @@
|
||||
# Tcl launcher script for the project
|
||||
namespace eval project_launcher {
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "project.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Perform actions related to this project.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean, sim, verify, test, view, elaborate\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
proc do_clean { root_dir } {
|
||||
variable dir "$root_dir/runs"
|
||||
|
||||
puts "Cleaning all files in directory $dir...\n"
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[catch { glob "$dir/*" } result] != 1} {
|
||||
file delete -force -- {*}[glob "$dir/*" ]
|
||||
}
|
||||
}
|
||||
|
||||
proc do_sim_icarus { root_dir verbose } {
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[file exists "$root_dir/scripts/run_iverilog.tcl"] == 1} {
|
||||
#global root_dir_loc $root_dir
|
||||
#source $root_dir/scripts/run_iverilog.tcl
|
||||
try {
|
||||
set results [exec tclsh $root_dir/scripts/run_iverilog.tcl $root_dir ]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running the script :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
if {[expr $verbose]} {
|
||||
# output the result of the execution
|
||||
puts $results
|
||||
}
|
||||
|
||||
} else {
|
||||
puts "The script run_iverilog.tcl does not exist in $root_dir/scripts"
|
||||
}
|
||||
}
|
||||
|
||||
proc do_sim_pytest { root_dir verbose } {
|
||||
|
||||
exec pytest $root_dir/tests/ >@stdout 2>@stderr
|
||||
}
|
||||
|
||||
proc do_elaborate { root_dir } {
|
||||
|
||||
exec $root_dir/scripts/run_elaborate.bat
|
||||
}
|
||||
|
||||
|
||||
proc do_formal { root_dir } {
|
||||
# We suppose that the sby file is meant to be run from the inside of the folder
|
||||
# hence we cd there
|
||||
if {[file pathtype $root_dir] != "absolute"} {
|
||||
set root_dir "../$root_dir"
|
||||
}
|
||||
#set root_dir [file normalize $root_dir]
|
||||
cd verification
|
||||
#variable fname [glob -nocomplain $root_dir/verification/*.sby]
|
||||
variable fname [glob -nocomplain *.sby]
|
||||
|
||||
if {[llength $fname]} {
|
||||
set fname [lindex $fname 0]
|
||||
puts "Using $fname file..."
|
||||
exec sby -f $fname --prefix $root_dir/runs/verification/counter >@stdout 2>@stderr
|
||||
} else {
|
||||
puts "There are no .sby files present..."
|
||||
cd ..
|
||||
return
|
||||
}
|
||||
cd ..
|
||||
}
|
||||
|
||||
proc do_view { root_dir } {
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[file exists "$root_dir/scripts/run_gtkwave.tcl"] == 1} {
|
||||
try {
|
||||
set results [exec tclsh $root_dir/scripts/run_gtkwave.tcl $root_dir ]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running the script :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
puts "The script run_gtkwave.tcl does not exist in $root_dir/scripts"
|
||||
}
|
||||
}
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
# Use origin directory path location variable, if specified in the tcl shell
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
variable action "help"
|
||||
|
||||
variable verbose false
|
||||
|
||||
if { $::argc > 0 } {
|
||||
for {set i 0} {$i < $::argc} {incr i} {
|
||||
set option [string trim [lindex $::argv $i]]
|
||||
switch -regexp -- $option {
|
||||
"--root" { incr i; set root_dir [lindex $::argv $i] }
|
||||
"--help" { print_help }
|
||||
"help" { print_help }
|
||||
"clean" { set action "clean" }
|
||||
"sim" {incr i; set action "sim_[lindex $::argv $i]" }
|
||||
"--verbose" { set verbose true }
|
||||
"-v" { set verbose true }
|
||||
{pytest|cocotb|test} {set action "pytest"}
|
||||
{formal|verify|verification} {set action "formal"}
|
||||
{view} {set action "view"}
|
||||
{elaborate} {set action "elaborate"}
|
||||
default {
|
||||
if { [regexp {^-} $option] } {
|
||||
puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print_help
|
||||
}
|
||||
|
||||
puts "Script started. The root dir is $root_dir. The action is: $action\n"
|
||||
|
||||
switch -regexp -- $action {
|
||||
"clean" { do_clean $root_dir }
|
||||
{sim_icarus|^sim_$|sim_iverilog} { do_sim_icarus $root_dir $verbose}
|
||||
{sim_cocotb|pytest} { do_sim_pytest $root_dir $verbose}
|
||||
"formal" { do_formal $root_dir}
|
||||
"view" {do_view $root_dir}
|
||||
"elaborate" {do_elaborate $root_dir}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
main
|
||||
|
||||
}
|
16
Help/presentation_examples/blink/scripts/run_elaborate.bat
Normal file
16
Help/presentation_examples/blink/scripts/run_elaborate.bat
Normal file
@@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
rem https://github.com/YosysHQ/apicula
|
||||
|
||||
set file_name=src\verilog\counter.v src\verilog\blink.v src\verilog\blink_top.v
|
||||
set constraints_file=constraints\blink_led.cst
|
||||
|
||||
yosys -p "read_verilog -sv %file_name%; synth_gowin -json runs\blink_led_c.json"
|
||||
|
||||
set DEVICE=GW2AR-LV18QN88C8/I7
|
||||
set BOARD=tangnano20k
|
||||
|
||||
nextpnr-himbaechel --json runs\blink_led_c.json --write runs\pnr_blink_led.json --device %DEVICE% --vopt cst=%constraints_file% --vopt family=GW2A-18C
|
||||
|
||||
gowin_pack -d %DEVICE% -o runs\blink_led_c.fs runs\pnr_blink_led.json
|
||||
|
||||
rem openfpgaloader -b %BOARD% blink_led_c.fs
|
88
Help/presentation_examples/blink/scripts/run_gtkwave.tcl
Normal file
88
Help/presentation_examples/blink/scripts/run_gtkwave.tcl
Normal file
@@ -0,0 +1,88 @@
|
||||
# Tcl script for iverilog simulation
|
||||
namespace eval gtkwave {
|
||||
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "run_gtkwave.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Runs the iverilog simulation.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
if { $::argc > 0 } {
|
||||
set root_dir [lindex $::argv 0]
|
||||
}
|
||||
|
||||
puts "Starting gtkwave. The root dir is: $root_dir"
|
||||
|
||||
# variable root [file dirname [file normalize [info script]]]
|
||||
# variable root [file dirname [file dirname [info script]]]
|
||||
variable root $root_dir
|
||||
|
||||
variable view_file $root/runs/sim/iverilog/blink_tb.vcd
|
||||
|
||||
variable gtkwave_script $root/scripts/gtk_wave_all_signals.tcl
|
||||
|
||||
proc run_view {res} {
|
||||
set name [file rootname $res]
|
||||
|
||||
# set iverilog_args "$sim_iverilog::additional_options -g2012 -Wall -I $sim_iverilog::source_path -Y .sv -y $sim_iverilog::source_path -o $sim_iverilog::output_dir/$name.vvp $sim_iverilog::tb_path/$tb $sim_iverilog::sources_full_path"
|
||||
#set gtkwave_args "-S $gtkwave::gtkwave_script $gtkwave::view_file"
|
||||
set gtkwave_args "$gtkwave::view_file"
|
||||
|
||||
#puts $gtkwave_args
|
||||
try {
|
||||
set results [exec gtkwave {*}$gtkwave_args]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running gtkwave :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
# output iverilog result
|
||||
puts $results
|
||||
|
||||
|
||||
}
|
||||
|
||||
run_view $root_dir
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# run main
|
||||
|
||||
main
|
||||
|
||||
}
|
133
Help/presentation_examples/blink/scripts/run_iverilog.tcl
Normal file
133
Help/presentation_examples/blink/scripts/run_iverilog.tcl
Normal file
@@ -0,0 +1,133 @@
|
||||
# Tcl script for iverilog simulation
|
||||
namespace eval sim_iverilog {
|
||||
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "run_iverilog.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Runs the iverilog simulation.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
if { $::argc > 0 } {
|
||||
set root_dir [lindex $::argv 0]
|
||||
}
|
||||
|
||||
puts "Starting simulation using iverilog. The root dir is: $root_dir"
|
||||
|
||||
# variable root [file dirname [file normalize [info script]]]
|
||||
# variable root [file dirname [file dirname [info script]]]
|
||||
variable root $root_dir
|
||||
|
||||
variable source_path $root/src/verilog
|
||||
|
||||
variable sources {blink.v}
|
||||
|
||||
variable tb_path $root/tests/verilog
|
||||
|
||||
variable test_benches {blink_tb.v}
|
||||
|
||||
proc append_path {root list} {
|
||||
set l {}
|
||||
foreach f $list {
|
||||
lappend l $root/$f
|
||||
}
|
||||
return $l
|
||||
}
|
||||
|
||||
variable sources_full_path [append_path $source_path $sources]
|
||||
variable tb_full_path [append_path $tb_path $test_benches]
|
||||
|
||||
variable output_dir $root/runs/sim/iverilog
|
||||
|
||||
variable additional_options "-D VCD_DUMP"
|
||||
|
||||
proc run_sim {tb} {
|
||||
set name [file rootname $tb]
|
||||
puts "Running test bench $name"
|
||||
|
||||
puts "Cleaning files..."
|
||||
|
||||
# file delete [glob -nocomplain $sim_iverilog::output_dir/*]
|
||||
|
||||
puts "Recreating path..."
|
||||
|
||||
file mkdir $sim_iverilog::output_dir
|
||||
|
||||
set iverilog_args "$sim_iverilog::additional_options -g2012 -Wall -I $sim_iverilog::source_path -Y .sv -y $sim_iverilog::source_path -o $sim_iverilog::output_dir/$name.vvp $sim_iverilog::tb_path/$tb $sim_iverilog::sources_full_path"
|
||||
|
||||
|
||||
try {
|
||||
set results [exec iverilog {*}$iverilog_args]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running iverilog :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
# output iverilog result
|
||||
puts $results
|
||||
|
||||
set cwd [pwd]
|
||||
|
||||
puts "Running vvp..."
|
||||
|
||||
set vvp_cmd "vvp $name.vvp -lxt2"
|
||||
|
||||
cd $sim_iverilog::output_dir
|
||||
|
||||
#puts [pwd]
|
||||
set results [exec {*}$vvp_cmd]
|
||||
|
||||
# output vvp result
|
||||
puts $results
|
||||
|
||||
cd $cwd
|
||||
|
||||
puts "All done..."
|
||||
|
||||
}
|
||||
|
||||
foreach tb $test_benches {
|
||||
run_sim $tb
|
||||
}
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# run main
|
||||
|
||||
main
|
||||
|
||||
}
|
34
Help/presentation_examples/blink/src/verilog/blink.v
Normal file
34
Help/presentation_examples/blink/src/verilog/blink.v
Normal file
@@ -0,0 +1,34 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
module blink #(
|
||||
parameter CLK_SPEED = 27_000_000
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
output reg led
|
||||
);
|
||||
|
||||
wire strobe;
|
||||
|
||||
localparam ONE_HALF_S = CLK_SPEED / 2;
|
||||
localparam ONE_S = CLK_SPEED ;
|
||||
localparam TWO_S = CLK_SPEED *2;
|
||||
|
||||
|
||||
localparam TIME = TWO_S;
|
||||
localparam TIME_WIDTH = $clog2(TIME);
|
||||
|
||||
initial led = 0;
|
||||
|
||||
counter #(.WIDTH(TIME_WIDTH), .INITIAL_VALUE(TIME)) counter_inst
|
||||
(
|
||||
.clk(clk),
|
||||
.reset(1'b0),
|
||||
.en(1'b1),
|
||||
.strobe(strobe)
|
||||
);
|
||||
|
||||
always_ff @(posedge clk)
|
||||
if(strobe) led <= !led;
|
||||
|
||||
endmodule
|
14
Help/presentation_examples/blink/src/verilog/blink_top.v
Normal file
14
Help/presentation_examples/blink/src/verilog/blink_top.v
Normal file
@@ -0,0 +1,14 @@
|
||||
module blink_top
|
||||
(
|
||||
input wire clk,
|
||||
output wire led
|
||||
);
|
||||
|
||||
blink #(
|
||||
.CLK_SPEED(27_000_000)
|
||||
) blink_inst (
|
||||
.clk(clk),
|
||||
.led(led)
|
||||
);
|
||||
|
||||
endmodule
|
71
Help/presentation_examples/blink/src/verilog/counter.v
Normal file
71
Help/presentation_examples/blink/src/verilog/counter.v
Normal file
@@ -0,0 +1,71 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
// Simple counter_reg with synchronous reset (and no load)
|
||||
//
|
||||
|
||||
module counter #(
|
||||
parameter WIDTH = 8,
|
||||
parameter INITIAL_VALUE = 8'h0f
|
||||
) (
|
||||
input wire clk, // global clock
|
||||
input wire reset, // synchronous reset signal
|
||||
input wire en, // enable signal
|
||||
output reg strobe // output strobe
|
||||
);
|
||||
|
||||
initial strobe = 0;
|
||||
|
||||
reg[WIDTH-1:0] counter_reg = INITIAL_VALUE;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
counter_reg <= INITIAL_VALUE;
|
||||
end
|
||||
else if (en) begin
|
||||
strobe <= 0;
|
||||
if (counter_reg == 0)
|
||||
counter_reg <= INITIAL_VALUE;
|
||||
else begin
|
||||
if (counter_reg == 1)
|
||||
strobe <= 1;
|
||||
counter_reg <= counter_reg - 1;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
`ifdef FORMAL
|
||||
|
||||
reg f_past_valid = 0;
|
||||
|
||||
always @* f_past_valid = !$initstate;
|
||||
|
||||
always @* begin
|
||||
assume (counter_reg <= INITIAL_VALUE);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
// if ($initstate) begin
|
||||
// assume(counter_reg==INITIAL_VALUE);
|
||||
// end
|
||||
// if (!$initstate && $past(en)==1 && !$past(reset)) begin
|
||||
if (f_past_valid && $past(en)==1 && !$past(reset)) begin
|
||||
if (counter_reg < INITIAL_VALUE)
|
||||
assert (counter_reg == $past(counter_reg) - 1);
|
||||
else begin
|
||||
assert(counter_reg == INITIAL_VALUE && $past(counter_reg)==0);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
`ifdef VERIFIC
|
||||
//internal_check: assert property (@(posedge clk)(counter_reg==11)|=>(counter_reg==10));
|
||||
//assert property (@(posedge clk)(counter_reg==11 && en && !reset)|=>(counter_reg==10));
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
@@ -0,0 +1,96 @@
|
||||
import cocotb
|
||||
from cocotb.triggers import Timer, RisingEdge, First
|
||||
|
||||
# from cocotb.triggers import FallingEdge, RisingEdge, First, Timer, Event
|
||||
|
||||
from cocotb_test.simulator import run
|
||||
import pytest
|
||||
import os
|
||||
|
||||
async def generate_clock(dut):
|
||||
"""Generate clock pulses."""
|
||||
|
||||
# for cycle in range(100):
|
||||
while True:
|
||||
dut.clk.value = 0
|
||||
await Timer(5, "ns")
|
||||
dut.clk.value = 1
|
||||
await Timer(5, "ns")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def counter_simple_test(dut):
|
||||
await cocotb.start(generate_clock(dut)) # run the clock "in the background"
|
||||
|
||||
|
||||
#dut._log.info("my_signal_1 is %s", dut.my_signal_1.value)
|
||||
|
||||
# await Timer(10000, units='ns')
|
||||
|
||||
#for i in range(dut.WRITE_NB.value):
|
||||
# await RisingEdge(dut.write_transaction)
|
||||
#for i in range(dut.READ_NB.value):
|
||||
# await RisingEdge(dut.read_transaction)
|
||||
#await Timer(400, units="ns")
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
dut.reset.value = 1
|
||||
await RisingEdge(dut.clk)
|
||||
dut.reset.value = 0
|
||||
dut.en.value = 1
|
||||
|
||||
await Timer(400, units="ns")
|
||||
await RisingEdge(dut.clk)
|
||||
dut.en.value = 0
|
||||
await Timer(50, units="ns")
|
||||
await RisingEdge(dut.clk)
|
||||
dut.en.value = 1
|
||||
await Timer(500, units="ns")
|
||||
|
||||
# assert strobe : have a new process counting strobes
|
||||
|
||||
|
||||
|
||||
def test_counter_runner():
|
||||
current_dir = os.path.dirname(__file__)
|
||||
root = "{current_dir}../.."
|
||||
print(f"root: {root}")
|
||||
run(
|
||||
# python_search=[os.path.join(current_dir, "../cocotb/")],
|
||||
python_search=[current_dir],
|
||||
verilog_sources=[
|
||||
f"{root}/src/verilog/counter.v",
|
||||
], # sources
|
||||
toplevel="counter", # top level HDL
|
||||
module="counter_test", # name of cocotb test module
|
||||
sim_build=f"{root}/runs/cocotb", # + "_".join(("{}={}".format(*i) for i in parameters.items())),
|
||||
# parameters = parameters,
|
||||
waves=1,
|
||||
)
|
||||
|
||||
@pytest.mark.skipif(os.getenv("SIM") == "verilator", reason="Custom for verilator")
|
||||
@pytest.mark.parametrize("parameters", [{"WIDTH": 4, "INITIAL_VALUE": 5}, {"WIDTH": 8, "INITIAL_VALUE": 15}, {"WIDTH": 8, "INITIAL_VALUE": 255}])
|
||||
def test_parametrized_counter_runner(parameters):
|
||||
current_dir = os.path.dirname(__file__)
|
||||
#from pathlib import Path
|
||||
#proj_path = Path(__file__).resolve().parent
|
||||
root = "{current_dir}../.."
|
||||
run(
|
||||
# python_search=[os.path.join(current_dir, "../cocotb/")],
|
||||
python_search=[current_dir],
|
||||
verilog_sources=[
|
||||
f"{root}/src/verilog/counter.v",
|
||||
], # sources
|
||||
toplevel="counter", # top level HDL
|
||||
module="counter_test", # name of cocotb test module
|
||||
sim_build=f"{root}/runs/cocotb/" + "_".join(("{}={}".format(*i) for i in parameters.items())),
|
||||
parameters = parameters,
|
||||
waves=1,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_counter_runner()
|
37
Help/presentation_examples/blink/tests/verilog/blink_tb.v
Normal file
37
Help/presentation_examples/blink/tests/verilog/blink_tb.v
Normal file
@@ -0,0 +1,37 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
module blink_tb ();
|
||||
|
||||
reg clk = 0;
|
||||
|
||||
initial forever #5 clk = !clk;
|
||||
|
||||
wire led;
|
||||
|
||||
|
||||
blink #(.CLK_SPEED(20)) bl (.clk(clk),.led(led));
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef VCD_DUMP
|
||||
$dumpfile("blink_tb.vcd");
|
||||
$dumpvars(0,blink_tb);
|
||||
`endif
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef END_TIME
|
||||
#`END_TIME $finish();
|
||||
`else
|
||||
#1000 $finish();
|
||||
`endif
|
||||
end
|
||||
|
||||
initial begin
|
||||
|
||||
#500 $finish();
|
||||
end
|
||||
|
||||
endmodule
|
27
Help/presentation_examples/blink/verification/counter1.sby
Normal file
27
Help/presentation_examples/blink/verification/counter1.sby
Normal file
@@ -0,0 +1,27 @@
|
||||
[tasks]
|
||||
bmc
|
||||
prove
|
||||
cover
|
||||
|
||||
[options]
|
||||
bmc: mode bmc
|
||||
prove: mode prove
|
||||
cover: mode cover
|
||||
bmc: depth 100
|
||||
|
||||
[engines]
|
||||
smtbmc
|
||||
#smtbmc z3
|
||||
#abc bmc3
|
||||
|
||||
|
||||
|
||||
[script]
|
||||
read -verific
|
||||
read -sv counter.v
|
||||
read -formal counter_formal.sv
|
||||
prep -top counter
|
||||
|
||||
[files]
|
||||
../src/verilog/counter.v
|
||||
counter_formal.sv
|
@@ -0,0 +1,48 @@
|
||||
`default_nettype none
|
||||
|
||||
module counter_formal (
|
||||
input wire clk, // global clock
|
||||
input wire reset, // synchronous reset signal
|
||||
(*anyseq*) input wire en, // enable signal
|
||||
input wire strobe, // output strobe
|
||||
input wire [counter.WIDTH-1:0] counter_reg
|
||||
|
||||
);
|
||||
|
||||
`ifdef VERIFIC
|
||||
internal_check: assert property (@(posedge clk)
|
||||
disable iff (reset)
|
||||
en && (counter_reg==11)|=>(counter_reg==10)) ;
|
||||
|
||||
decrease_enable_check: assert property (@(posedge clk)
|
||||
disable iff (reset || !en)
|
||||
(counter_reg >0 ) |=> (counter_reg == $past(counter_reg) - 1));
|
||||
|
||||
roll_enable_check: assert property (@(posedge clk)
|
||||
disable iff (reset || !en)
|
||||
(counter_reg == 0 ) |=> (counter_reg == counter.INITIAL_VALUE));
|
||||
|
||||
max_value_assert_check: assert property (
|
||||
@(posedge clk)
|
||||
(counter_reg <= counter.INITIAL_VALUE)
|
||||
);
|
||||
|
||||
cover_0: cover property(
|
||||
@(posedge clk)
|
||||
(counter_reg == 0)
|
||||
);
|
||||
|
||||
cover_2stb: cover property(
|
||||
@(posedge clk)
|
||||
(strobe == 1) |-> ##[+] (strobe == 1)
|
||||
);
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
bind counter counter_formal counter_f_inst(.*);
|
||||
|
||||
|
||||
//testing: assert property (@(posedge clk)(counter_reg==111)|=>(counter_reg==10));
|
4
Help/presentation_examples/blink_vivado/.gitignore
vendored
Normal file
4
Help/presentation_examples/blink_vivado/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
runs
|
||||
.vscode
|
||||
workspace.code-workspace
|
||||
*.pyc
|
@@ -0,0 +1,4 @@
|
||||
IO_LOC "led" 15;
|
||||
IO_PORT "led" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
|
||||
IO_LOC "clk" 4;
|
||||
IO_PORT "clk" PULL_MODE=UP BANK_VCCIO=1.8;
|
2
Help/presentation_examples/blink_vivado/project.bat
Normal file
2
Help/presentation_examples/blink_vivado/project.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@call c:\tools\oss-cad-suite\environment.bat
|
||||
@tclsh scripts\project.tcl %*
|
@@ -0,0 +1,3 @@
|
||||
sv work ../tests/verilog/blink_tb.v
|
||||
sv work ../src/verilog/blink.v -i src/verilog
|
||||
sv work ../src/verilog/counter.v -i src/verilog
|
18
Help/presentation_examples/blink_vivado/run_xsim.bat
Normal file
18
Help/presentation_examples/blink_vivado/run_xsim.bat
Normal file
@@ -0,0 +1,18 @@
|
||||
rem @echo off
|
||||
set PATH=%PATH%;c:\Xilinx\Vivado\2023.2\bin
|
||||
set top=blink_tb
|
||||
if not exist output mkdir output
|
||||
rem call xvlog %FILES%
|
||||
rem IF %ERRORLEVEL% NEQ 0 goto end
|
||||
rem call xelab -debug typical %top% -s top_sim
|
||||
echo Calling XELAB...
|
||||
call xelab -nolog -prj project\blink.prj -debug typical %top% -s top_sim --override_timeunit --override_timeprecision --timescale 1ns/1ps
|
||||
rem IF %ERRORLEVEL% NEQ 0 goto end
|
||||
rem call xsim top_sim -t xsim_run.tcl
|
||||
echo Calling XSIM...
|
||||
call xsim top_sim -nolog -R --wdb output/top_sim.wdb
|
||||
start gtkwave %top%.vcd %top%.gtkw --script gtk_wave_all_signals.tcl
|
||||
del xsim.jou
|
||||
del xelab.pb
|
||||
del webtalk*
|
||||
:end
|
@@ -0,0 +1,20 @@
|
||||
puts "Starting TCL script"
|
||||
#set path test1b_tb
|
||||
#gtkwave::forceOpenTreeNode $path
|
||||
set nfacs [ gtkwave::getNumFacs ]
|
||||
puts "There are $nfacs signals"
|
||||
set l [list]
|
||||
|
||||
for {set i 0} {$i < $nfacs } {incr i} {
|
||||
set facname [ gtkwave::getFacName $i ]
|
||||
set numdots [ expr {[llength [split $facname .]] - 1}]
|
||||
# puts "$numdots"
|
||||
if {$numdots == 1} {
|
||||
lappend l "$facname"
|
||||
puts "Added signal $facname"
|
||||
}
|
||||
}
|
||||
|
||||
set num_added [ gtkwave::addSignalsFromList $l ]
|
||||
gtkwave::setZoomRangeTimes [ gtkwave::getMinTime ] [ gtkwave::getMaxTime ]
|
||||
puts "Start time [ gtkwave::getMinTime ] end time: [ gtkwave::getMaxTime ]"
|
184
Help/presentation_examples/blink_vivado/scripts/project.tcl
Normal file
184
Help/presentation_examples/blink_vivado/scripts/project.tcl
Normal file
@@ -0,0 +1,184 @@
|
||||
# Tcl launcher script for the project
|
||||
namespace eval project_launcher {
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "project.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Perform actions related to this project.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean, sim, verify, test, view, elaborate\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
proc do_clean { root_dir } {
|
||||
variable dir "$root_dir/runs"
|
||||
|
||||
puts "Cleaning all files in directory $dir...\n"
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[catch { glob "$dir/*" } result] != 1} {
|
||||
file delete -force -- {*}[glob "$dir/*" ]
|
||||
}
|
||||
}
|
||||
|
||||
proc do_sim_icarus { root_dir verbose } {
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[file exists "$root_dir/scripts/run_iverilog.tcl"] == 1} {
|
||||
#global root_dir_loc $root_dir
|
||||
#source $root_dir/scripts/run_iverilog.tcl
|
||||
try {
|
||||
set results [exec tclsh $root_dir/scripts/run_iverilog.tcl $root_dir ]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running the script :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
if {[expr $verbose]} {
|
||||
# output the result of the execution
|
||||
puts $results
|
||||
}
|
||||
|
||||
} else {
|
||||
puts "The script run_iverilog.tcl does not exist in $root_dir/scripts"
|
||||
}
|
||||
}
|
||||
|
||||
proc do_sim_pytest { root_dir verbose } {
|
||||
|
||||
exec pytest $root_dir/tests/ >@stdout 2>@stderr
|
||||
}
|
||||
|
||||
proc do_elaborate { root_dir } {
|
||||
|
||||
exec $root_dir/scripts/run_elaborate.bat
|
||||
}
|
||||
|
||||
|
||||
proc do_formal { root_dir } {
|
||||
# We suppose that the sby file is meant to be run from the inside of the folder
|
||||
# hence we cd there
|
||||
if {[file pathtype $root_dir] != "absolute"} {
|
||||
set root_dir "../$root_dir"
|
||||
}
|
||||
#set root_dir [file normalize $root_dir]
|
||||
cd verification
|
||||
#variable fname [glob -nocomplain $root_dir/verification/*.sby]
|
||||
variable fname [glob -nocomplain *.sby]
|
||||
|
||||
if {[llength $fname]} {
|
||||
set fname [lindex $fname 0]
|
||||
puts "Using $fname file..."
|
||||
exec sby -f $fname --prefix $root_dir/runs/verification/counter >@stdout 2>@stderr
|
||||
} else {
|
||||
puts "There are no .sby files present..."
|
||||
cd ..
|
||||
return
|
||||
}
|
||||
cd ..
|
||||
}
|
||||
|
||||
proc do_view { root_dir } {
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[file exists "$root_dir/scripts/run_gtkwave.tcl"] == 1} {
|
||||
try {
|
||||
set results [exec tclsh $root_dir/scripts/run_gtkwave.tcl $root_dir ]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running the script :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
puts "The script run_gtkwave.tcl does not exist in $root_dir/scripts"
|
||||
}
|
||||
}
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
# Use origin directory path location variable, if specified in the tcl shell
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
variable action "help"
|
||||
|
||||
variable verbose false
|
||||
|
||||
if { $::argc > 0 } {
|
||||
for {set i 0} {$i < $::argc} {incr i} {
|
||||
set option [string trim [lindex $::argv $i]]
|
||||
switch -regexp -- $option {
|
||||
"--root" { incr i; set root_dir [lindex $::argv $i] }
|
||||
"--help" { print_help }
|
||||
"help" { print_help }
|
||||
"clean" { set action "clean" }
|
||||
"sim" {incr i; set action "sim_[lindex $::argv $i]" }
|
||||
"--verbose" { set verbose true }
|
||||
"-v" { set verbose true }
|
||||
{pytest|cocotb|test} {set action "pytest"}
|
||||
{formal|verify|verification} {set action "formal"}
|
||||
{view} {set action "view"}
|
||||
{elaborate} {set action "elaborate"}
|
||||
default {
|
||||
if { [regexp {^-} $option] } {
|
||||
puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print_help
|
||||
}
|
||||
|
||||
puts "Script started. The root dir is $root_dir. The action is: $action\n"
|
||||
|
||||
switch -regexp -- $action {
|
||||
"clean" { do_clean $root_dir }
|
||||
{sim_icarus|^sim_$|sim_iverilog} { do_sim_icarus $root_dir $verbose}
|
||||
{sim_cocotb|pytest} { do_sim_pytest $root_dir $verbose}
|
||||
"formal" { do_formal $root_dir}
|
||||
"view" {do_view $root_dir}
|
||||
"elaborate" {do_elaborate $root_dir}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
main
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
rem https://github.com/YosysHQ/apicula
|
||||
|
||||
set file_name=src\verilog\counter.v src\verilog\blink.v src\verilog\blink_top.v
|
||||
set constraints_file=constraints\blink_led.cst
|
||||
|
||||
yosys -p "read_verilog -sv %file_name%; synth_gowin -json runs\blink_led_c.json"
|
||||
|
||||
set DEVICE=GW2AR-LV18QN88C8/I7
|
||||
set BOARD=tangnano20k
|
||||
|
||||
nextpnr-himbaechel --json runs\blink_led_c.json --write runs\pnr_blink_led.json --device %DEVICE% --vopt cst=%constraints_file% --vopt family=GW2A-18C
|
||||
|
||||
gowin_pack -d %DEVICE% -o runs\blink_led_c.fs runs\pnr_blink_led.json
|
||||
|
||||
rem openfpgaloader -b %BOARD% blink_led_c.fs
|
@@ -0,0 +1,88 @@
|
||||
# Tcl script for iverilog simulation
|
||||
namespace eval gtkwave {
|
||||
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "run_gtkwave.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Runs the iverilog simulation.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
if { $::argc > 0 } {
|
||||
set root_dir [lindex $::argv 0]
|
||||
}
|
||||
|
||||
puts "Starting gtkwave. The root dir is: $root_dir"
|
||||
|
||||
# variable root [file dirname [file normalize [info script]]]
|
||||
# variable root [file dirname [file dirname [info script]]]
|
||||
variable root $root_dir
|
||||
|
||||
variable view_file $root/runs/sim/iverilog/blink_tb.vcd
|
||||
|
||||
variable gtkwave_script $root/scripts/gtk_wave_all_signals.tcl
|
||||
|
||||
proc run_view {res} {
|
||||
set name [file rootname $res]
|
||||
|
||||
# set iverilog_args "$sim_iverilog::additional_options -g2012 -Wall -I $sim_iverilog::source_path -Y .sv -y $sim_iverilog::source_path -o $sim_iverilog::output_dir/$name.vvp $sim_iverilog::tb_path/$tb $sim_iverilog::sources_full_path"
|
||||
#set gtkwave_args "-S $gtkwave::gtkwave_script $gtkwave::view_file"
|
||||
set gtkwave_args "$gtkwave::view_file"
|
||||
|
||||
#puts $gtkwave_args
|
||||
try {
|
||||
set results [exec gtkwave {*}$gtkwave_args]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running gtkwave :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
# output iverilog result
|
||||
puts $results
|
||||
|
||||
|
||||
}
|
||||
|
||||
run_view $root_dir
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# run main
|
||||
|
||||
main
|
||||
|
||||
}
|
133
Help/presentation_examples/blink_vivado/scripts/run_iverilog.tcl
Normal file
133
Help/presentation_examples/blink_vivado/scripts/run_iverilog.tcl
Normal file
@@ -0,0 +1,133 @@
|
||||
# Tcl script for iverilog simulation
|
||||
namespace eval sim_iverilog {
|
||||
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "run_iverilog.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Runs the iverilog simulation.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
if { $::argc > 0 } {
|
||||
set root_dir [lindex $::argv 0]
|
||||
}
|
||||
|
||||
puts "Starting simulation using iverilog. The root dir is: $root_dir"
|
||||
|
||||
# variable root [file dirname [file normalize [info script]]]
|
||||
# variable root [file dirname [file dirname [info script]]]
|
||||
variable root $root_dir
|
||||
|
||||
variable source_path $root/src/verilog
|
||||
|
||||
variable sources {blink.v}
|
||||
|
||||
variable tb_path $root/tests/verilog
|
||||
|
||||
variable test_benches {blink_tb.v}
|
||||
|
||||
proc append_path {root list} {
|
||||
set l {}
|
||||
foreach f $list {
|
||||
lappend l $root/$f
|
||||
}
|
||||
return $l
|
||||
}
|
||||
|
||||
variable sources_full_path [append_path $source_path $sources]
|
||||
variable tb_full_path [append_path $tb_path $test_benches]
|
||||
|
||||
variable output_dir $root/runs/sim/iverilog
|
||||
|
||||
variable additional_options "-D VCD_DUMP"
|
||||
|
||||
proc run_sim {tb} {
|
||||
set name [file rootname $tb]
|
||||
puts "Running test bench $name"
|
||||
|
||||
puts "Cleaning files..."
|
||||
|
||||
# file delete [glob -nocomplain $sim_iverilog::output_dir/*]
|
||||
|
||||
puts "Recreating path..."
|
||||
|
||||
file mkdir $sim_iverilog::output_dir
|
||||
|
||||
set iverilog_args "$sim_iverilog::additional_options -g2012 -Wall -I $sim_iverilog::source_path -Y .sv -y $sim_iverilog::source_path -o $sim_iverilog::output_dir/$name.vvp $sim_iverilog::tb_path/$tb $sim_iverilog::sources_full_path"
|
||||
|
||||
|
||||
try {
|
||||
set results [exec iverilog {*}$iverilog_args]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running iverilog :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
# output iverilog result
|
||||
puts $results
|
||||
|
||||
set cwd [pwd]
|
||||
|
||||
puts "Running vvp..."
|
||||
|
||||
set vvp_cmd "vvp $name.vvp -lxt2"
|
||||
|
||||
cd $sim_iverilog::output_dir
|
||||
|
||||
#puts [pwd]
|
||||
set results [exec {*}$vvp_cmd]
|
||||
|
||||
# output vvp result
|
||||
puts $results
|
||||
|
||||
cd $cwd
|
||||
|
||||
puts "All done..."
|
||||
|
||||
}
|
||||
|
||||
foreach tb $test_benches {
|
||||
run_sim $tb
|
||||
}
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# run main
|
||||
|
||||
main
|
||||
|
||||
}
|
34
Help/presentation_examples/blink_vivado/src/verilog/blink.v
Normal file
34
Help/presentation_examples/blink_vivado/src/verilog/blink.v
Normal file
@@ -0,0 +1,34 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
module blink #(
|
||||
parameter CLK_SPEED = 27_000_000
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
output reg led
|
||||
);
|
||||
|
||||
wire strobe;
|
||||
|
||||
localparam ONE_HALF_S = CLK_SPEED / 2;
|
||||
localparam ONE_S = CLK_SPEED ;
|
||||
localparam TWO_S = CLK_SPEED *2;
|
||||
|
||||
|
||||
localparam TIME = TWO_S;
|
||||
localparam TIME_WIDTH = $clog2(TIME);
|
||||
|
||||
initial led = 0;
|
||||
|
||||
counter #(.WIDTH(TIME_WIDTH), .INITIAL_VALUE(TIME)) counter_inst
|
||||
(
|
||||
.clk(clk),
|
||||
.reset(1'b0),
|
||||
.en(1'b1),
|
||||
.strobe(strobe)
|
||||
);
|
||||
|
||||
always_ff @(posedge clk)
|
||||
if(strobe) led <= !led;
|
||||
|
||||
endmodule
|
@@ -0,0 +1,14 @@
|
||||
module blink_top
|
||||
(
|
||||
input wire clk,
|
||||
output wire led
|
||||
);
|
||||
|
||||
blink #(
|
||||
.CLK_SPEED(27_000_000)
|
||||
) blink_inst (
|
||||
.clk(clk),
|
||||
.led(led)
|
||||
);
|
||||
|
||||
endmodule
|
@@ -0,0 +1,71 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
// Simple counter_reg with synchronous reset (and no load)
|
||||
//
|
||||
|
||||
module counter #(
|
||||
parameter WIDTH = 8,
|
||||
parameter INITIAL_VALUE = 8'h0f
|
||||
) (
|
||||
input wire clk, // global clock
|
||||
input wire reset, // synchronous reset signal
|
||||
input wire en, // enable signal
|
||||
output reg strobe // output strobe
|
||||
);
|
||||
|
||||
initial strobe = 0;
|
||||
|
||||
reg[WIDTH-1:0] counter_reg = INITIAL_VALUE;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
counter_reg <= INITIAL_VALUE;
|
||||
end
|
||||
else if (en) begin
|
||||
strobe <= 0;
|
||||
if (counter_reg == 0)
|
||||
counter_reg <= INITIAL_VALUE;
|
||||
else begin
|
||||
if (counter_reg == 1)
|
||||
strobe <= 1;
|
||||
counter_reg <= counter_reg - 1;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
`ifdef FORMAL
|
||||
|
||||
reg f_past_valid = 0;
|
||||
|
||||
always @* f_past_valid = !$initstate;
|
||||
|
||||
always @* begin
|
||||
assume (counter_reg <= INITIAL_VALUE);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
// if ($initstate) begin
|
||||
// assume(counter_reg==INITIAL_VALUE);
|
||||
// end
|
||||
// if (!$initstate && $past(en)==1 && !$past(reset)) begin
|
||||
if (f_past_valid && $past(en)==1 && !$past(reset)) begin
|
||||
if (counter_reg < INITIAL_VALUE)
|
||||
assert (counter_reg == $past(counter_reg) - 1);
|
||||
else begin
|
||||
assert(counter_reg == INITIAL_VALUE && $past(counter_reg)==0);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
`ifdef VERIFIC
|
||||
//internal_check: assert property (@(posedge clk)(counter_reg==11)|=>(counter_reg==10));
|
||||
//assert property (@(posedge clk)(counter_reg==11 && en && !reset)|=>(counter_reg==10));
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
@@ -0,0 +1,37 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
module blink_tb ();
|
||||
|
||||
reg clk = 0;
|
||||
|
||||
initial forever #5 clk = !clk;
|
||||
|
||||
wire led;
|
||||
|
||||
|
||||
blink #(.CLK_SPEED(20)) bl (.clk(clk),.led(led));
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef VCD_DUMP
|
||||
$dumpfile("blink_tb.vcd");
|
||||
$dumpvars(0,blink_tb);
|
||||
`endif
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef END_TIME
|
||||
#`END_TIME $finish();
|
||||
`else
|
||||
#1000 $finish();
|
||||
`endif
|
||||
end
|
||||
|
||||
initial begin
|
||||
|
||||
#500 $finish();
|
||||
end
|
||||
|
||||
endmodule
|
@@ -0,0 +1,27 @@
|
||||
[tasks]
|
||||
bmc
|
||||
prove
|
||||
cover
|
||||
|
||||
[options]
|
||||
bmc: mode bmc
|
||||
prove: mode prove
|
||||
cover: mode cover
|
||||
bmc: depth 100
|
||||
|
||||
[engines]
|
||||
smtbmc
|
||||
#smtbmc z3
|
||||
#abc bmc3
|
||||
|
||||
|
||||
|
||||
[script]
|
||||
read -verific
|
||||
read -sv counter.v
|
||||
read -formal counter_formal.sv
|
||||
prep -top counter
|
||||
|
||||
[files]
|
||||
../src/verilog/counter.v
|
||||
counter_formal.sv
|
@@ -0,0 +1,48 @@
|
||||
`default_nettype none
|
||||
|
||||
module counter_formal (
|
||||
input wire clk, // global clock
|
||||
input wire reset, // synchronous reset signal
|
||||
(*anyseq*) input wire en, // enable signal
|
||||
input wire strobe, // output strobe
|
||||
input wire [counter.WIDTH-1:0] counter_reg
|
||||
|
||||
);
|
||||
|
||||
`ifdef VERIFIC
|
||||
internal_check: assert property (@(posedge clk)
|
||||
disable iff (reset)
|
||||
en && (counter_reg==11)|=>(counter_reg==10)) ;
|
||||
|
||||
decrease_enable_check: assert property (@(posedge clk)
|
||||
disable iff (reset || !en)
|
||||
(counter_reg >0 ) |=> (counter_reg == $past(counter_reg) - 1));
|
||||
|
||||
roll_enable_check: assert property (@(posedge clk)
|
||||
disable iff (reset || !en)
|
||||
(counter_reg == 0 ) |=> (counter_reg == counter.INITIAL_VALUE));
|
||||
|
||||
max_value_assert_check: assert property (
|
||||
@(posedge clk)
|
||||
(counter_reg <= counter.INITIAL_VALUE)
|
||||
);
|
||||
|
||||
cover_0: cover property(
|
||||
@(posedge clk)
|
||||
(counter_reg == 0)
|
||||
);
|
||||
|
||||
cover_2stb: cover property(
|
||||
@(posedge clk)
|
||||
(strobe == 1) |-> ##[+] (strobe == 1)
|
||||
);
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
bind counter counter_formal counter_f_inst(.*);
|
||||
|
||||
|
||||
//testing: assert property (@(posedge clk)(counter_reg==111)|=>(counter_reg==10));
|
BIN
Help/presentation_examples/blink_vivado/xsim.dir/work/blink.sdb
Normal file
BIN
Help/presentation_examples/blink_vivado/xsim.dir/work/blink.sdb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
0.7
|
||||
2020.2
|
||||
Oct 13 2023
|
||||
20:47:58
|
||||
c:/ver/roots/programming/FPGA/presentation_examples/blink_vivado/src/verilog/blink.v,1745688175,systemVerilog,,,,blink,,,src/verilog,,,,,
|
||||
c:/ver/roots/programming/FPGA/presentation_examples/blink_vivado/src/verilog/counter.v,1678724585,systemVerilog,,,,counter,,,src/verilog,,,,,
|
||||
c:/ver/roots/programming/FPGA/presentation_examples/blink_vivado/tests/verilog/blink_tb.v,1745687036,systemVerilog,,,,blink_tb,,,,,,,,
|
4
Help/presentation_examples/counter/.gitignore
vendored
Normal file
4
Help/presentation_examples/counter/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
runs
|
||||
.vscode
|
||||
workspace.code-workspace
|
||||
*.pyc
|
2
Help/presentation_examples/counter/project.bat
Normal file
2
Help/presentation_examples/counter/project.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
@call c:\tools\oss-cad-suite\environment.bat
|
||||
@tclsh scripts\project.tcl %*
|
@@ -0,0 +1,20 @@
|
||||
puts "Starting TCL script"
|
||||
#set path test1b_tb
|
||||
#gtkwave::forceOpenTreeNode $path
|
||||
set nfacs [ gtkwave::getNumFacs ]
|
||||
puts "There are $nfacs signals"
|
||||
set l [list]
|
||||
|
||||
for {set i 0} {$i < $nfacs } {incr i} {
|
||||
set facname [ gtkwave::getFacName $i ]
|
||||
set numdots [ expr {[llength [split $facname .]] - 1}]
|
||||
# puts "$numdots"
|
||||
if {$numdots == 1} {
|
||||
lappend l "$facname"
|
||||
puts "Added signal $facname"
|
||||
}
|
||||
}
|
||||
|
||||
set num_added [ gtkwave::addSignalsFromList $l ]
|
||||
gtkwave::setZoomRangeTimes [ gtkwave::getMinTime ] [ gtkwave::getMaxTime ]
|
||||
puts "Start time [ gtkwave::getMinTime ] end time: [ gtkwave::getMaxTime ]"
|
176
Help/presentation_examples/counter/scripts/project.tcl
Normal file
176
Help/presentation_examples/counter/scripts/project.tcl
Normal file
@@ -0,0 +1,176 @@
|
||||
# Tcl launcher script for the project
|
||||
namespace eval project_launcher {
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "project.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Perform actions related to this project.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean, sim, verify, test, view\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
proc do_clean { root_dir } {
|
||||
variable dir "$root_dir/runs"
|
||||
|
||||
puts "Cleaning all files in directory $dir...\n"
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[catch { glob "$dir/*" } result] != 1} {
|
||||
file delete -force -- {*}[glob "$dir/*" ]
|
||||
}
|
||||
}
|
||||
|
||||
proc do_sim_icarus { root_dir verbose } {
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[file exists "$root_dir/scripts/run_iverilog.tcl"] == 1} {
|
||||
#global root_dir_loc $root_dir
|
||||
#source $root_dir/scripts/run_iverilog.tcl
|
||||
try {
|
||||
set results [exec tclsh $root_dir/scripts/run_iverilog.tcl $root_dir ]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running the script :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
if {[expr $verbose]} {
|
||||
# output the result of the execution
|
||||
puts $results
|
||||
}
|
||||
|
||||
} else {
|
||||
puts "The script run_iverilog.tcl does not exist in $root_dir/scripts"
|
||||
}
|
||||
}
|
||||
|
||||
proc do_sim_pytest { root_dir verbose } {
|
||||
|
||||
exec pytest $root_dir/tests/ >@stdout 2>@stderr
|
||||
}
|
||||
|
||||
proc do_formal { root_dir } {
|
||||
# We suppose that the sby file is meant to be run from the inside of the folder
|
||||
# hence we cd there
|
||||
if {[file pathtype $root_dir] != "absolute"} {
|
||||
set root_dir "../$root_dir"
|
||||
}
|
||||
#set root_dir [file normalize $root_dir]
|
||||
cd verification
|
||||
#variable fname [glob -nocomplain $root_dir/verification/*.sby]
|
||||
variable fname [glob -nocomplain *.sby]
|
||||
|
||||
if {[llength $fname]} {
|
||||
set fname [lindex $fname 0]
|
||||
puts "Using $fname file..."
|
||||
exec sby -f $fname --prefix $root_dir/runs/verification/counter >@stdout 2>@stderr
|
||||
} else {
|
||||
puts "There are no .sby files present..."
|
||||
cd ..
|
||||
return
|
||||
}
|
||||
cd ..
|
||||
}
|
||||
|
||||
proc do_view { root_dir } {
|
||||
|
||||
# Checking if the folder is empty to avoid error
|
||||
if {[file exists "$root_dir/scripts/run_gtkwave.tcl"] == 1} {
|
||||
try {
|
||||
set results [exec tclsh $root_dir/scripts/run_gtkwave.tcl $root_dir ]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running the script :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
puts "The script run_gtkwave.tcl does not exist in $root_dir/scripts"
|
||||
}
|
||||
}
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
# Use origin directory path location variable, if specified in the tcl shell
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
variable action "help"
|
||||
|
||||
variable verbose false
|
||||
|
||||
if { $::argc > 0 } {
|
||||
for {set i 0} {$i < $::argc} {incr i} {
|
||||
set option [string trim [lindex $::argv $i]]
|
||||
switch -regexp -- $option {
|
||||
"--root" { incr i; set root_dir [lindex $::argv $i] }
|
||||
"--help" { print_help }
|
||||
"help" { print_help }
|
||||
"clean" { set action "clean" }
|
||||
"sim" {incr i; set action "sim_[lindex $::argv $i]" }
|
||||
"--verbose" { set verbose true }
|
||||
"-v" { set verbose true }
|
||||
{pytest|cocotb|test} {set action "pytest"}
|
||||
{formal|verify|verification} {set action "formal"}
|
||||
{view} {set action "view"}
|
||||
default {
|
||||
if { [regexp {^-} $option] } {
|
||||
puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print_help
|
||||
}
|
||||
|
||||
puts "Script started. The root dir is $root_dir. The action is: $action\n"
|
||||
|
||||
switch -regexp -- $action {
|
||||
"clean" { do_clean $root_dir }
|
||||
{sim_icarus|^sim_$|sim_iverilog} { do_sim_icarus $root_dir $verbose}
|
||||
{sim_cocotb|pytest} { do_sim_pytest $root_dir $verbose}
|
||||
"formal" { do_formal $root_dir}
|
||||
"view" {do_view $root_dir}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
main
|
||||
|
||||
}
|
88
Help/presentation_examples/counter/scripts/run_gtkwave.tcl
Normal file
88
Help/presentation_examples/counter/scripts/run_gtkwave.tcl
Normal file
@@ -0,0 +1,88 @@
|
||||
# Tcl script for iverilog simulation
|
||||
namespace eval gtkwave {
|
||||
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "run_gtkwave.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Runs the iverilog simulation.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
if { $::argc > 0 } {
|
||||
set root_dir [lindex $::argv 0]
|
||||
}
|
||||
|
||||
puts "Starting gtkwave. The root dir is: $root_dir"
|
||||
|
||||
# variable root [file dirname [file normalize [info script]]]
|
||||
# variable root [file dirname [file dirname [info script]]]
|
||||
variable root $root_dir
|
||||
|
||||
variable view_file $root/runs/sim/iverilog/counter_tb.vcd
|
||||
|
||||
variable gtkwave_script $root/scripts/gtk_wave_all_signals.tcl
|
||||
|
||||
proc run_view {res} {
|
||||
set name [file rootname $res]
|
||||
|
||||
# set iverilog_args "$sim_iverilog::additional_options -g2012 -Wall -I $sim_iverilog::source_path -Y .sv -y $sim_iverilog::source_path -o $sim_iverilog::output_dir/$name.vvp $sim_iverilog::tb_path/$tb $sim_iverilog::sources_full_path"
|
||||
#set gtkwave_args "-S $gtkwave::gtkwave_script $gtkwave::view_file"
|
||||
set gtkwave_args "$gtkwave::view_file"
|
||||
|
||||
#puts $gtkwave_args
|
||||
try {
|
||||
set results [exec gtkwave {*}$gtkwave_args]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running gtkwave :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
# output iverilog result
|
||||
puts $results
|
||||
|
||||
|
||||
}
|
||||
|
||||
run_view $root_dir
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# run main
|
||||
|
||||
main
|
||||
|
||||
}
|
133
Help/presentation_examples/counter/scripts/run_iverilog.tcl
Normal file
133
Help/presentation_examples/counter/scripts/run_iverilog.tcl
Normal file
@@ -0,0 +1,133 @@
|
||||
# Tcl script for iverilog simulation
|
||||
namespace eval sim_iverilog {
|
||||
|
||||
|
||||
# Help information for this script
|
||||
proc print_help {} {
|
||||
variable script_file "run_iverilog.tcl"
|
||||
puts "\nDescription:"
|
||||
puts "Runs the iverilog simulation.\n"
|
||||
puts "Syntax:"
|
||||
puts "$script_file"
|
||||
puts "$script_file \[action\] \[args\]"
|
||||
puts "Usage:"
|
||||
puts "Name Description"
|
||||
puts "-------------------------------------------------------------------------"
|
||||
puts "\[action\] Determine the action to be performed. Default value: help\n"
|
||||
puts " Current actions: help, clean\n"
|
||||
puts "\[args\] Arguments related to the action.\n"
|
||||
puts " --root <dir> changes the root reference for the project.\n"
|
||||
puts "-------------------------------------------------------------------------\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
proc main {} {
|
||||
|
||||
variable root_dir
|
||||
# Set the reference directory to where the script is
|
||||
#set root_dir [file dirname [info script]]
|
||||
|
||||
# Set the reference directory for source file relative paths (by default the value is script directory path)
|
||||
set root_dir "."
|
||||
|
||||
if { [info exists ::root_dir_loc] } {
|
||||
set root_dir $::root_dir_loc
|
||||
}
|
||||
|
||||
if { $::argc > 0 } {
|
||||
set root_dir [lindex $::argv 0]
|
||||
}
|
||||
|
||||
puts "Starting simulation using iverilog. The root dir is: $root_dir"
|
||||
|
||||
# variable root [file dirname [file normalize [info script]]]
|
||||
# variable root [file dirname [file dirname [info script]]]
|
||||
variable root $root_dir
|
||||
|
||||
variable source_path $root/src/verilog
|
||||
|
||||
variable sources {counter.v}
|
||||
|
||||
variable tb_path $root/tests/verilog
|
||||
|
||||
variable test_benches {counter_tb.v}
|
||||
|
||||
proc append_path {root list} {
|
||||
set l {}
|
||||
foreach f $list {
|
||||
lappend l $root/$f
|
||||
}
|
||||
return $l
|
||||
}
|
||||
|
||||
variable sources_full_path [append_path $source_path $sources]
|
||||
variable tb_full_path [append_path $tb_path $test_benches]
|
||||
|
||||
variable output_dir $root/runs/sim/iverilog
|
||||
|
||||
variable additional_options "-D VCD_DUMP"
|
||||
|
||||
proc run_sim {tb} {
|
||||
set name [file rootname $tb]
|
||||
puts "Running test bench $name"
|
||||
|
||||
puts "Cleaning files..."
|
||||
|
||||
# file delete [glob -nocomplain $sim_iverilog::output_dir/*]
|
||||
|
||||
puts "Recreating path..."
|
||||
|
||||
file mkdir $sim_iverilog::output_dir
|
||||
|
||||
set iverilog_args "$sim_iverilog::additional_options -g2012 -Wall -I $sim_iverilog::source_path -Y .sv -y $sim_iverilog::source_path -o $sim_iverilog::output_dir/$name.vvp $sim_iverilog::tb_path/$tb $sim_iverilog::sources_full_path"
|
||||
|
||||
|
||||
try {
|
||||
set results [exec iverilog {*}$iverilog_args]
|
||||
set status 0
|
||||
} trap CHILDSTATUS {results options} {
|
||||
set status [lindex [dict get $options -errorcode] 2]
|
||||
}
|
||||
|
||||
if {$status != 0} {
|
||||
puts "Problem running iverilog :"
|
||||
puts $results
|
||||
return
|
||||
}
|
||||
|
||||
# output iverilog result
|
||||
puts $results
|
||||
|
||||
set cwd [pwd]
|
||||
|
||||
puts "Running vvp..."
|
||||
|
||||
set vvp_cmd "vvp $name.vvp -lxt2"
|
||||
|
||||
cd $sim_iverilog::output_dir
|
||||
|
||||
#puts [pwd]
|
||||
set results [exec {*}$vvp_cmd]
|
||||
|
||||
# output vvp result
|
||||
puts $results
|
||||
|
||||
cd $cwd
|
||||
|
||||
puts "All done..."
|
||||
|
||||
}
|
||||
|
||||
foreach tb $test_benches {
|
||||
run_sim $tb
|
||||
}
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# run main
|
||||
|
||||
main
|
||||
|
||||
}
|
101
Help/presentation_examples/counter/src/verilog/a.out
Normal file
101
Help/presentation_examples/counter/src/verilog/a.out
Normal file
@@ -0,0 +1,101 @@
|
||||
#!
|
||||
:ivl_version "13.0 (devel)" "(s20250103-24-g6088a26d7-dirty)";
|
||||
:ivl_delay_selection "TYPICAL";
|
||||
:vpi_time_precision - 12;
|
||||
:vpi_module "c:\tools\OSS-CA~1\lib\ivl\system.vpi";
|
||||
:vpi_module "c:\tools\OSS-CA~1\lib\ivl\vhdl_sys.vpi";
|
||||
:vpi_module "c:\tools\OSS-CA~1\lib\ivl\vhdl_textio.vpi";
|
||||
:vpi_module "c:\tools\OSS-CA~1\lib\ivl\v2005_math.vpi";
|
||||
:vpi_module "c:\tools\OSS-CA~1\lib\ivl\va_math.vpi";
|
||||
:vpi_module "c:\tools\OSS-CA~1\lib\ivl\v2009.vpi";
|
||||
S_00000173f996e8a0 .scope package, "$unit" "$unit" 2 1;
|
||||
.timescale 0 0;
|
||||
S_00000173f996ea30 .scope module, "example1_tb" "example1_tb" 3 4;
|
||||
.timescale -9 -12;
|
||||
v00000173f996bd00_0 .var "clk", 0 0;
|
||||
v00000173f996bda0_0 .net "strobe", 0 0, v00000173f996b350_0; 1 drivers
|
||||
S_00000173f9967280 .scope module, "count" "example1" 3 12, 4 2 0, S_00000173f996ea30;
|
||||
.timescale -9 -12;
|
||||
.port_info 0 /INPUT 1 "clk";
|
||||
.port_info 1 /OUTPUT 1 "strobe";
|
||||
P_00000173f9a28a80 .param/l "WIDTH" 1 4 7, +C4<00000000000000000000000000000100>;
|
||||
v00000173f996ebc0_0 .net "clk", 0 0, v00000173f996bd00_0; 1 drivers
|
||||
v00000173f996a0c0_0 .var "count", 3 0;
|
||||
v00000173f996b350_0 .var "strobe", 0 0;
|
||||
E_00000173f9a28880 .event posedge, v00000173f996ebc0_0;
|
||||
E_00000173f9a28380 .event anyedge, v00000173f996a0c0_0;
|
||||
.scope S_00000173f9967280;
|
||||
T_0 ;
|
||||
%pushi/vec4 0, 0, 4;
|
||||
%store/vec4 v00000173f996a0c0_0, 0, 4;
|
||||
%end;
|
||||
.thread T_0, $init;
|
||||
.scope S_00000173f9967280;
|
||||
T_1 ;
|
||||
Ewait_0 .event/or E_00000173f9a28380, E_0x0;
|
||||
%wait Ewait_0;
|
||||
%load/vec4 v00000173f996a0c0_0;
|
||||
%and/r;
|
||||
%store/vec4 v00000173f996b350_0, 0, 1;
|
||||
%jmp T_1;
|
||||
.thread T_1, $push;
|
||||
.scope S_00000173f9967280;
|
||||
T_2 ;
|
||||
%wait E_00000173f9a28880;
|
||||
%load/vec4 v00000173f996a0c0_0;
|
||||
%addi 1, 0, 4;
|
||||
%assign/vec4 v00000173f996a0c0_0, 0;
|
||||
%jmp T_2;
|
||||
.thread T_2;
|
||||
.scope S_00000173f996ea30;
|
||||
T_3 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v00000173f996bd00_0, 0, 1;
|
||||
%end;
|
||||
.thread T_3, $init;
|
||||
.scope S_00000173f996ea30;
|
||||
T_4 ;
|
||||
T_4.0 ;
|
||||
%delay 5000, 0;
|
||||
%load/vec4 v00000173f996bd00_0;
|
||||
%nor/r;
|
||||
%store/vec4 v00000173f996bd00_0, 0, 1;
|
||||
%jmp T_4.0;
|
||||
T_4.1 ;
|
||||
%end;
|
||||
.thread T_4;
|
||||
.scope S_00000173f996ea30;
|
||||
T_5 ;
|
||||
%vpi_call/w 3 17 "$dumpfile", "counter_tb.vcd" {0 0 0};
|
||||
%vpi_call/w 3 18 "$dumpvars", 32'sb00000000000000000000000000000000, S_00000173f996ea30 {0 0 0};
|
||||
%end;
|
||||
.thread T_5;
|
||||
.scope S_00000173f996ea30;
|
||||
T_6 ;
|
||||
%delay 1000000, 0;
|
||||
%vpi_call/w 3 27 "$finish" {0 0 0};
|
||||
%end;
|
||||
.thread T_6;
|
||||
.scope S_00000173f996ea30;
|
||||
T_7 ;
|
||||
%delay 500000, 0;
|
||||
%vpi_call/w 3 32 "$finish" {0 0 0};
|
||||
%end;
|
||||
.thread T_7;
|
||||
.scope S_00000173f996ea30;
|
||||
T_8 ;
|
||||
%wait E_00000173f9a28880;
|
||||
%load/vec4 v00000173f996bda0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_8.0, 8;
|
||||
%vpi_call/w 3 36 "$display", "Strobe" {0 0 0};
|
||||
T_8.0 ;
|
||||
%jmp T_8;
|
||||
.thread T_8;
|
||||
# The file index is used to find the file name in the following table.
|
||||
:file_names 5;
|
||||
"N/A";
|
||||
"<interactive>";
|
||||
"-";
|
||||
"example1_tb.v";
|
||||
"example1.v";
|
71
Help/presentation_examples/counter/src/verilog/counter.v
Normal file
71
Help/presentation_examples/counter/src/verilog/counter.v
Normal file
@@ -0,0 +1,71 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
// Simple counter_reg with synchronous reset (and no load)
|
||||
//
|
||||
|
||||
module counter #(
|
||||
parameter WIDTH = 8,
|
||||
parameter INITIAL_VALUE = 8'h0f
|
||||
) (
|
||||
input wire clk, // global clock
|
||||
input wire reset, // synchronous reset signal
|
||||
input wire en, // enable signal
|
||||
output reg strobe // output strobe
|
||||
);
|
||||
|
||||
initial strobe = 0;
|
||||
|
||||
reg[WIDTH-1:0] counter_reg = INITIAL_VALUE;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (reset) begin
|
||||
counter_reg <= INITIAL_VALUE;
|
||||
end
|
||||
else if (en) begin
|
||||
strobe <= 0;
|
||||
if (counter_reg == 0)
|
||||
counter_reg <= INITIAL_VALUE;
|
||||
else begin
|
||||
if (counter_reg == 1)
|
||||
strobe <= 1;
|
||||
counter_reg <= counter_reg - 1;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
`ifdef FORMAL
|
||||
|
||||
reg f_past_valid = 0;
|
||||
|
||||
always @* f_past_valid = !$initstate;
|
||||
|
||||
always @* begin
|
||||
assume (counter_reg <= INITIAL_VALUE);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
// if ($initstate) begin
|
||||
// assume(counter_reg==INITIAL_VALUE);
|
||||
// end
|
||||
// if (!$initstate && $past(en)==1 && !$past(reset)) begin
|
||||
if (f_past_valid && $past(en)==1 && !$past(reset)) begin
|
||||
if (counter_reg < INITIAL_VALUE)
|
||||
assert (counter_reg == $past(counter_reg) - 1);
|
||||
else begin
|
||||
assert(counter_reg == INITIAL_VALUE && $past(counter_reg)==0);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
`endif
|
||||
|
||||
|
||||
`ifdef VERIFIC
|
||||
//internal_check: assert property (@(posedge clk)(counter_reg==11)|=>(counter_reg==10));
|
||||
//assert property (@(posedge clk)(counter_reg==11 && en && !reset)|=>(counter_reg==10));
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
286
Help/presentation_examples/counter/src/verilog/counter_tb.vcd
Normal file
286
Help/presentation_examples/counter/src/verilog/counter_tb.vcd
Normal file
@@ -0,0 +1,286 @@
|
||||
$date
|
||||
Sat Apr 26 17:20:46 2025
|
||||
$end
|
||||
$version
|
||||
Icarus Verilog
|
||||
$end
|
||||
$timescale
|
||||
1ps
|
||||
$end
|
||||
$scope module example1_tb $end
|
||||
$var wire 1 ! strobe $end
|
||||
$var reg 1 " clk $end
|
||||
$scope module count $end
|
||||
$var wire 1 " clk $end
|
||||
$var parameter 32 # WIDTH $end
|
||||
$var reg 4 $ count [3:0] $end
|
||||
$var reg 1 ! strobe $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
$comment Show the parameter values. $end
|
||||
$dumpall
|
||||
b100 #
|
||||
$end
|
||||
#0
|
||||
$dumpvars
|
||||
b0 $
|
||||
0"
|
||||
0!
|
||||
$end
|
||||
#5000
|
||||
b1 $
|
||||
1"
|
||||
#10000
|
||||
0"
|
||||
#15000
|
||||
b10 $
|
||||
1"
|
||||
#20000
|
||||
0"
|
||||
#25000
|
||||
b11 $
|
||||
1"
|
||||
#30000
|
||||
0"
|
||||
#35000
|
||||
b100 $
|
||||
1"
|
||||
#40000
|
||||
0"
|
||||
#45000
|
||||
b101 $
|
||||
1"
|
||||
#50000
|
||||
0"
|
||||
#55000
|
||||
b110 $
|
||||
1"
|
||||
#60000
|
||||
0"
|
||||
#65000
|
||||
b111 $
|
||||
1"
|
||||
#70000
|
||||
0"
|
||||
#75000
|
||||
b1000 $
|
||||
1"
|
||||
#80000
|
||||
0"
|
||||
#85000
|
||||
b1001 $
|
||||
1"
|
||||
#90000
|
||||
0"
|
||||
#95000
|
||||
b1010 $
|
||||
1"
|
||||
#100000
|
||||
0"
|
||||
#105000
|
||||
b1011 $
|
||||
1"
|
||||
#110000
|
||||
0"
|
||||
#115000
|
||||
b1100 $
|
||||
1"
|
||||
#120000
|
||||
0"
|
||||
#125000
|
||||
b1101 $
|
||||
1"
|
||||
#130000
|
||||
0"
|
||||
#135000
|
||||
b1110 $
|
||||
1"
|
||||
#140000
|
||||
0"
|
||||
#145000
|
||||
1!
|
||||
b1111 $
|
||||
1"
|
||||
#150000
|
||||
0"
|
||||
#155000
|
||||
0!
|
||||
b0 $
|
||||
1"
|
||||
#160000
|
||||
0"
|
||||
#165000
|
||||
b1 $
|
||||
1"
|
||||
#170000
|
||||
0"
|
||||
#175000
|
||||
b10 $
|
||||
1"
|
||||
#180000
|
||||
0"
|
||||
#185000
|
||||
b11 $
|
||||
1"
|
||||
#190000
|
||||
0"
|
||||
#195000
|
||||
b100 $
|
||||
1"
|
||||
#200000
|
||||
0"
|
||||
#205000
|
||||
b101 $
|
||||
1"
|
||||
#210000
|
||||
0"
|
||||
#215000
|
||||
b110 $
|
||||
1"
|
||||
#220000
|
||||
0"
|
||||
#225000
|
||||
b111 $
|
||||
1"
|
||||
#230000
|
||||
0"
|
||||
#235000
|
||||
b1000 $
|
||||
1"
|
||||
#240000
|
||||
0"
|
||||
#245000
|
||||
b1001 $
|
||||
1"
|
||||
#250000
|
||||
0"
|
||||
#255000
|
||||
b1010 $
|
||||
1"
|
||||
#260000
|
||||
0"
|
||||
#265000
|
||||
b1011 $
|
||||
1"
|
||||
#270000
|
||||
0"
|
||||
#275000
|
||||
b1100 $
|
||||
1"
|
||||
#280000
|
||||
0"
|
||||
#285000
|
||||
b1101 $
|
||||
1"
|
||||
#290000
|
||||
0"
|
||||
#295000
|
||||
b1110 $
|
||||
1"
|
||||
#300000
|
||||
0"
|
||||
#305000
|
||||
1!
|
||||
b1111 $
|
||||
1"
|
||||
#310000
|
||||
0"
|
||||
#315000
|
||||
0!
|
||||
b0 $
|
||||
1"
|
||||
#320000
|
||||
0"
|
||||
#325000
|
||||
b1 $
|
||||
1"
|
||||
#330000
|
||||
0"
|
||||
#335000
|
||||
b10 $
|
||||
1"
|
||||
#340000
|
||||
0"
|
||||
#345000
|
||||
b11 $
|
||||
1"
|
||||
#350000
|
||||
0"
|
||||
#355000
|
||||
b100 $
|
||||
1"
|
||||
#360000
|
||||
0"
|
||||
#365000
|
||||
b101 $
|
||||
1"
|
||||
#370000
|
||||
0"
|
||||
#375000
|
||||
b110 $
|
||||
1"
|
||||
#380000
|
||||
0"
|
||||
#385000
|
||||
b111 $
|
||||
1"
|
||||
#390000
|
||||
0"
|
||||
#395000
|
||||
b1000 $
|
||||
1"
|
||||
#400000
|
||||
0"
|
||||
#405000
|
||||
b1001 $
|
||||
1"
|
||||
#410000
|
||||
0"
|
||||
#415000
|
||||
b1010 $
|
||||
1"
|
||||
#420000
|
||||
0"
|
||||
#425000
|
||||
b1011 $
|
||||
1"
|
||||
#430000
|
||||
0"
|
||||
#435000
|
||||
b1100 $
|
||||
1"
|
||||
#440000
|
||||
0"
|
||||
#445000
|
||||
b1101 $
|
||||
1"
|
||||
#450000
|
||||
0"
|
||||
#455000
|
||||
b1110 $
|
||||
1"
|
||||
#460000
|
||||
0"
|
||||
#465000
|
||||
1!
|
||||
b1111 $
|
||||
1"
|
||||
#470000
|
||||
0"
|
||||
#475000
|
||||
0!
|
||||
b0 $
|
||||
1"
|
||||
#480000
|
||||
0"
|
||||
#485000
|
||||
b1 $
|
||||
1"
|
||||
#490000
|
||||
0"
|
||||
#495000
|
||||
b10 $
|
||||
1"
|
||||
#500000
|
||||
0"
|
32
Help/presentation_examples/counter/src/verilog/example1.v
Normal file
32
Help/presentation_examples/counter/src/verilog/example1.v
Normal file
@@ -0,0 +1,32 @@
|
||||
`default_nettype none
|
||||
module example1 (
|
||||
input wire clk, // global clock
|
||||
output reg strobe // output strobe
|
||||
);
|
||||
|
||||
localparam WIDTH=4;
|
||||
|
||||
reg[WIDTH-1:0] count = 0;
|
||||
|
||||
always_comb begin
|
||||
strobe = &count;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
count <= count + 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
/*
|
||||
module top_module (
|
||||
input in1,
|
||||
input in2,
|
||||
input in3,
|
||||
output out);
|
||||
|
||||
always_comb
|
||||
out = ~(in1 ^ in2) ^ in3;
|
||||
|
||||
endmodule
|
||||
*/
|
39
Help/presentation_examples/counter/src/verilog/example1_tb.v
Normal file
39
Help/presentation_examples/counter/src/verilog/example1_tb.v
Normal file
@@ -0,0 +1,39 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
module example1_tb ();
|
||||
|
||||
reg clk = 0;
|
||||
|
||||
initial forever #5 clk = !clk;
|
||||
|
||||
wire strobe;
|
||||
|
||||
example1 count (.clk(clk), .strobe(strobe));
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef VCD_DUMP
|
||||
$dumpfile("counter_tb.vcd");
|
||||
$dumpvars(0,example1_tb);
|
||||
`endif
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef END_TIME
|
||||
#`END_TIME $finish();
|
||||
`else
|
||||
#1000 $finish();
|
||||
`endif
|
||||
end
|
||||
|
||||
initial begin
|
||||
#500 $finish();
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (strobe) $display("Strobe");
|
||||
end
|
||||
|
||||
endmodule
|
@@ -0,0 +1,96 @@
|
||||
import cocotb
|
||||
from cocotb.triggers import Timer, RisingEdge, First
|
||||
|
||||
# from cocotb.triggers import FallingEdge, RisingEdge, First, Timer, Event
|
||||
|
||||
from cocotb_test.simulator import run
|
||||
import pytest
|
||||
import os
|
||||
|
||||
async def generate_clock(dut):
|
||||
"""Generate clock pulses."""
|
||||
|
||||
# for cycle in range(100):
|
||||
while True:
|
||||
dut.clk.value = 0
|
||||
await Timer(5, "ns")
|
||||
dut.clk.value = 1
|
||||
await Timer(5, "ns")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def counter_simple_test(dut):
|
||||
await cocotb.start(generate_clock(dut)) # run the clock "in the background"
|
||||
|
||||
|
||||
#dut._log.info("my_signal_1 is %s", dut.my_signal_1.value)
|
||||
|
||||
# await Timer(10000, units='ns')
|
||||
|
||||
#for i in range(dut.WRITE_NB.value):
|
||||
# await RisingEdge(dut.write_transaction)
|
||||
#for i in range(dut.READ_NB.value):
|
||||
# await RisingEdge(dut.read_transaction)
|
||||
#await Timer(400, units="ns")
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
dut.reset.value = 1
|
||||
await RisingEdge(dut.clk)
|
||||
dut.reset.value = 0
|
||||
dut.en.value = 1
|
||||
|
||||
await Timer(400, units="ns")
|
||||
await RisingEdge(dut.clk)
|
||||
dut.en.value = 0
|
||||
await Timer(50, units="ns")
|
||||
await RisingEdge(dut.clk)
|
||||
dut.en.value = 1
|
||||
await Timer(500, units="ns")
|
||||
|
||||
# assert strobe : have a new process counting strobes
|
||||
|
||||
|
||||
|
||||
def test_counter_runner():
|
||||
current_dir = os.path.dirname(__file__)
|
||||
root = "{current_dir}../.."
|
||||
print(f"root: {root}")
|
||||
run(
|
||||
# python_search=[os.path.join(current_dir, "../cocotb/")],
|
||||
python_search=[current_dir],
|
||||
verilog_sources=[
|
||||
f"{root}/src/verilog/counter.v",
|
||||
], # sources
|
||||
toplevel="counter", # top level HDL
|
||||
module="counter_test", # name of cocotb test module
|
||||
sim_build=f"{root}/runs/cocotb", # + "_".join(("{}={}".format(*i) for i in parameters.items())),
|
||||
# parameters = parameters,
|
||||
waves=1,
|
||||
)
|
||||
|
||||
@pytest.mark.skipif(os.getenv("SIM") == "verilator", reason="Custom for verilator")
|
||||
@pytest.mark.parametrize("parameters", [{"WIDTH": 4, "INITIAL_VALUE": 5}, {"WIDTH": 8, "INITIAL_VALUE": 15}, {"WIDTH": 8, "INITIAL_VALUE": 255}])
|
||||
def test_parametrized_counter_runner(parameters):
|
||||
current_dir = os.path.dirname(__file__)
|
||||
#from pathlib import Path
|
||||
#proj_path = Path(__file__).resolve().parent
|
||||
root = "{current_dir}../.."
|
||||
run(
|
||||
# python_search=[os.path.join(current_dir, "../cocotb/")],
|
||||
python_search=[current_dir],
|
||||
verilog_sources=[
|
||||
f"{root}/src/verilog/counter.v",
|
||||
], # sources
|
||||
toplevel="counter", # top level HDL
|
||||
module="counter_test", # name of cocotb test module
|
||||
sim_build=f"{root}/runs/cocotb/" + "_".join(("{}={}".format(*i) for i in parameters.items())),
|
||||
parameters = parameters,
|
||||
waves=1,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_counter_runner()
|
@@ -0,0 +1,49 @@
|
||||
`timescale 1ns/1ps
|
||||
`default_nettype none
|
||||
|
||||
module counter_tb ();
|
||||
|
||||
reg clk = 0;
|
||||
|
||||
initial forever #5 clk = !clk;
|
||||
|
||||
wire strobe;
|
||||
|
||||
reg reset = 1'b0;
|
||||
reg en = 1'b1;
|
||||
|
||||
counter #(.WIDTH(8),.INITIAL_VALUE(15)) count (.clk(clk),.en(en), .reset(reset), .strobe(strobe));
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef VCD_DUMP
|
||||
$dumpfile("counter_tb.vcd");
|
||||
$dumpvars(0,counter_tb);
|
||||
`endif
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
`ifdef END_TIME
|
||||
#`END_TIME $finish();
|
||||
`else
|
||||
#1000 $finish();
|
||||
`endif
|
||||
end
|
||||
|
||||
initial begin
|
||||
@(posedge clk) reset = 1;
|
||||
@(posedge clk) reset = 0;
|
||||
en = 1;
|
||||
#400;
|
||||
@(posedge clk) en = 0;
|
||||
#50;
|
||||
@(posedge clk) en = 1;
|
||||
#500 $finish();
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (strobe) $display("Strobe");
|
||||
end
|
||||
|
||||
endmodule
|
27
Help/presentation_examples/counter/verification/counter1.sby
Normal file
27
Help/presentation_examples/counter/verification/counter1.sby
Normal file
@@ -0,0 +1,27 @@
|
||||
[tasks]
|
||||
bmc
|
||||
prove
|
||||
cover
|
||||
|
||||
[options]
|
||||
bmc: mode bmc
|
||||
prove: mode prove
|
||||
cover: mode cover
|
||||
bmc: depth 100
|
||||
|
||||
[engines]
|
||||
smtbmc
|
||||
#smtbmc z3
|
||||
#abc bmc3
|
||||
|
||||
|
||||
|
||||
[script]
|
||||
read -verific
|
||||
read -sv counter.v
|
||||
read -formal counter_formal.sv
|
||||
prep -top counter
|
||||
|
||||
[files]
|
||||
../src/verilog/counter.v
|
||||
counter_formal.sv
|
@@ -0,0 +1,48 @@
|
||||
`default_nettype none
|
||||
|
||||
module counter_formal (
|
||||
input wire clk, // global clock
|
||||
input wire reset, // synchronous reset signal
|
||||
(*anyseq*) input wire en, // enable signal
|
||||
input wire strobe, // output strobe
|
||||
input wire [counter.WIDTH-1:0] counter_reg
|
||||
|
||||
);
|
||||
|
||||
`ifdef VERIFIC
|
||||
internal_check: assert property (@(posedge clk)
|
||||
disable iff (reset)
|
||||
en && (counter_reg==11)|=>(counter_reg==10)) ;
|
||||
|
||||
decrease_enable_check: assert property (@(posedge clk)
|
||||
disable iff (reset || !en)
|
||||
(counter_reg >0 ) |=> (counter_reg == $past(counter_reg) - 1));
|
||||
|
||||
roll_enable_check: assert property (@(posedge clk)
|
||||
disable iff (reset || !en)
|
||||
(counter_reg == 0 ) |=> (counter_reg == counter.INITIAL_VALUE));
|
||||
|
||||
max_value_assert_check: assert property (
|
||||
@(posedge clk)
|
||||
(counter_reg <= counter.INITIAL_VALUE)
|
||||
);
|
||||
|
||||
cover_0: cover property(
|
||||
@(posedge clk)
|
||||
(counter_reg == 0)
|
||||
);
|
||||
|
||||
cover_2stb: cover property(
|
||||
@(posedge clk)
|
||||
(strobe == 1) |-> ##[+] (strobe == 1)
|
||||
);
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
bind counter counter_formal counter_f_inst(.*);
|
||||
|
||||
|
||||
//testing: assert property (@(posedge clk)(counter_reg==111)|=>(counter_reg==10));
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user