aboutsummaryrefslogtreecommitdiff
path: root/verif/formal/simple_alu/simple_alu_fv.sv
blob: 98c05a786658fc5de29409b947552ce0e57b7723 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// Formal verification module for simple_alu.
// All ports are inputs - this module only observes DUT signals, never drives them.
// Instantiated via simple_alu_top_fv.sv wrapper (bind unsupported in open-source Yosys).
module simple_alu_fv (
    input logic        clk_i,
    input logic [31:0] a_i,
    input logic [31:0] b_i,
    input logic        sel_i,
    input logic        rst_ni,

    input logic [31:0] y_i,
    input logic        overflow_i
  );

    // -------------------------------------------------------------------------
    // Initial assumptions - constrain starting state so solver doesn't
    // explore garbage initial register values
    // -------------------------------------------------------------------------
    initial assume (~rst_ni);
    initial assume (y_i == '0);
    initial assume (overflow_i == 1'b0);

    //assertion check: if rst deasserted, y tied to 0
    //assertions are what we want to prove, formal verification is the engine that proves it
    // property p_rst_y;
    //     @(posedge clk_i)
    //     ~rst_ni |=> (y_i=='0);
    // endproperty
    // a_rst_y: assert property (p_rst_y)
    //     else $error("RESET CHECK FAILED: rst_ni=%0b y_i=%0h, expected y=0", rst_ni, y_i);

    // Reset check - y must be 0 one cycle after reset asserts (active low)
    always @(posedge clk_i) begin
        if ($past(~rst_ni)) begin
            assert (y_i == '0);
            assert (overflow_i == 0);
        end
    end

    // -------------------------------------------------------------------------
    // Cover statements - solver finds shortest path to reach each state
    // These generate VCD traces you can inspect in GTKWave
    // -------------------------------------------------------------------------

    always @(posedge clk_i) begin
        cover ($past(sel_i == 0) && overflow_i == 1'b1);  // addition overflow
        cover ($past(sel_i == 1) && overflow_i == 1'b1);  // subtraction underflow
    end

endmodule