formal verification stuff
This commit is contained in:
@@ -6,6 +6,7 @@ YOSYS = yosys
|
|||||||
PNR = nextpnr-ice40
|
PNR = nextpnr-ice40
|
||||||
IPACK = icepack
|
IPACK = icepack
|
||||||
BURN = iceFUNprog
|
BURN = iceFUNprog
|
||||||
|
SBY = sby
|
||||||
|
|
||||||
VERILATOR=verilator
|
VERILATOR=verilator
|
||||||
VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e "s/^.*=\s*//"')
|
VERILATOR_ROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e "s/^.*=\s*//"')
|
||||||
@@ -13,9 +14,11 @@ VINC := $(VERILATOR_ROOT)/include
|
|||||||
|
|
||||||
RTL_SRC := $(wildcard rtl/*.v)
|
RTL_SRC := $(wildcard rtl/*.v)
|
||||||
SIM_SRC := $(wildcard sim/*.cc)
|
SIM_SRC := $(wildcard sim/*.cc)
|
||||||
|
FV_SRC := sim/top.sby
|
||||||
|
|
||||||
BUILD_DIR := ./build
|
BUILD_DIR := ./build
|
||||||
|
|
||||||
.PHONY: all burn
|
.PHONY: all burn fv clean
|
||||||
all: $(SIM_TARGET) $(BIN_TARGET)
|
all: $(SIM_TARGET) $(BIN_TARGET)
|
||||||
|
|
||||||
# -GWIDTH=5 allows passing parameter to verilog module
|
# -GWIDTH=5 allows passing parameter to verilog module
|
||||||
@@ -51,6 +54,8 @@ $(BIN_TARGET): $(BUILD_DIR)/top.json $(PCF) $(TIMING)
|
|||||||
burn: $(BIN_TARGET)
|
burn: $(BIN_TARGET)
|
||||||
@$(BURN) $<
|
@$(BURN) $<
|
||||||
|
|
||||||
.PHONY: clean
|
fv:
|
||||||
|
@$(SBY) -f $(FV_SRC) -d $(BUILD_DIR)/fv
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
|
|||||||
@@ -56,6 +56,44 @@ module top(i_clk, o_led, lcol1);
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
`ifdef FORMAL
|
||||||
|
// led_index should never go beyond 13
|
||||||
|
always @(*)
|
||||||
|
assert(led_index <= 4'hd);
|
||||||
|
|
||||||
|
// I prefix all of the registers (or wires) I use in formal
|
||||||
|
// verification with f_, to distinguish them from the rest of the
|
||||||
|
// project.
|
||||||
|
reg f_valid_output;
|
||||||
|
always @(*)
|
||||||
|
begin
|
||||||
|
// Determining if the output is valid or not is a rather
|
||||||
|
// complex task--unusual for a typical assertion. Here, we'll
|
||||||
|
// use f_valid_output and a series of _blocking_ statements
|
||||||
|
// to determine if the output is one of our valid outputs.
|
||||||
|
f_valid_output = 0;
|
||||||
|
|
||||||
|
case(obuf)
|
||||||
|
8'h01: f_valid_output = 1'b1;
|
||||||
|
8'h02: f_valid_output = 1'b1;
|
||||||
|
8'h04: f_valid_output = 1'b1;
|
||||||
|
8'h08: f_valid_output = 1'b1;
|
||||||
|
8'h10: f_valid_output = 1'b1;
|
||||||
|
8'h20: f_valid_output = 1'b1;
|
||||||
|
8'h40: f_valid_output = 1'b1;
|
||||||
|
8'h80: f_valid_output = 1'b1;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
assert(f_valid_output);
|
||||||
|
|
||||||
|
// SV supports a $onehot function which we could've also used
|
||||||
|
// depending upon your version of Yosys. This function will
|
||||||
|
// be true if one, and only one, bit in the argument is true.
|
||||||
|
// Hence we might have said
|
||||||
|
// assert($onehot(o_led));
|
||||||
|
// and avoided this case statement entirely.
|
||||||
|
end
|
||||||
|
`endif
|
||||||
/* shift reg
|
/* shift reg
|
||||||
// shifting bit
|
// shifting bit
|
||||||
always @(posedge clk_12MHz)
|
always @(posedge clk_12MHz)
|
||||||
|
|||||||
13
fsm/sim/top.sby
Normal file
13
fsm/sim/top.sby
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[options]
|
||||||
|
mode prove
|
||||||
|
|
||||||
|
[engines]
|
||||||
|
smtbmc
|
||||||
|
|
||||||
|
[script]
|
||||||
|
read -formal *.v
|
||||||
|
prep -top top
|
||||||
|
|
||||||
|
[files]
|
||||||
|
rtl/top.v
|
||||||
|
rtl/clk_gen.v
|
||||||
Reference in New Issue
Block a user