data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp
 line:4: before: "parameter"
1: b'%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:8: Define or directive not defined: \'`mname\'\nmodule  `mname()`;\n        ^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:8: syntax error, unexpected \'(\', expecting IDENTIFIER or PACKAGE-IDENTIFIER or TYPE-IDENTIFIER\nmodule  `mname()`;\n               ^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:97: syntax error, unexpected always_ff\nalways_ff @(posedge clk or negedge rst_n) begin\n^~~~~~~~~\n%Warning-STMTDLY: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:147: Unsupported: Ignoring delay on this delayed statement.\n        #(CLK_PERIOD/10);\n        ^\n                  ... Use "/* verilator lint_off STMTDLY */" and lint_on around source to disable this message.\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:152: Unsupported or unknown PLI call: $urandom_range\n            op_a_w = $urandom_range(2**DataWidth - 1,0);\n                     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:153: Unsupported or unknown PLI call: $urandom_range\n            op_b_w = {2{16\'($urandom_range(31,0))}};\n                            ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:154: Unsupported or unknown PLI call: $urandom_range\n            op_c_w = $urandom_range(2**DataWidth - 1,0);\n                     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:155: Unsupported or unknown PLI call: $urandom_range\n            op_a_msb_w = $urandom_range(2**DataWidth - 1,0);\n                         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:156: Unsupported or unknown PLI call: $urandom_range\n            op_b_msb_w = $urandom_range(2**DataWidth - 1,0);\n                         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:157: Unsupported or unknown PLI call: $urandom_range\n            op_d_w = $urandom_range(1,0);\n                     ^~~~~~~~~~~~~~\n%Warning-STMTDLY: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:162: Unsupported: Ignoring delay on this delayed statement.\n        #(CLK_PERIOD*9/10);\n        ^\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:171: syntax error, unexpected assign\nassign mad_full = (data0_w*data1_w) + data2_w;\n^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:173: syntax error, unexpected assign\nassign full_sum = data0_w + data1_w + data2_w + bit0_w;\n^~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:179: syntax error, unexpected always_comb\nalways_comb begin\n^~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:369: Unsupported or unknown PLI call: $urandom_range\n                    data1_w = {2{16\'($urandom_range(16,0))}}; \n                                     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:376: Unsupported or unknown PLI call: $urandom_range\n                    data1_w = {2{16\'($urandom_range(16,0))}}; \n                                     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/209644662/hardware/generator_z/pe_new/pe/verif/test_pe/test_pe_tb.svp:383: Unsupported or unknown PLI call: $urandom_range\n                    data1_w = {2{16\'($urandom_range(16,0))}}; \n                                     ^~~~~~~~~~~~~~\n%Error: Exiting due to 15 error(s), 2 warning(s)\n'
module  `mname()`;

localparam DataWidth = 16;

logic                   clk;
logic                   clk_en;
logic                   rst_n;

logic [2*DataWidth-1:0]       cfg_d;
logic [7:0]             cfg_a;
logic                   cfg_en;
logic [DataWidth-1:0]       data0;
logic [DataWidth-1:0]       data1;
logic [DataWidth-1:0]       data2;
logic                   bit0;
logic                   bit1;
logic                   bit2;
logic [DataWidth-1:0]       res;
logic                   res_p;
logic [DataWidth-1:0]       read_data;
logic [DataWidth-1:0]       temp_data;

logic [2*DataWidth-1:0]       cfg_d_w;
logic [7:0]             cfg_a_w;
logic                   cfg_en_w;
logic [DataWidth-1:0]       data0_w;
logic [DataWidth-1:0]       data1_w;
logic [DataWidth-1:0]       data2_w;
logic [DataWidth-1:0]       data0_msb_w;
logic [DataWidth-1:0]       data1_msb_w;
logic                   bit0_w;
logic                   bit1_w;
logic                   bit2_w;
logic [DataWidth-1:0]     exp_res;
logic                     exp_res_p;
logic [DataWidth-1:0]     exp_res_next;
logic                     exp_res_p_next;
logic [DataWidth-1:0]   cmp_res;
logic                   cmp_res_p;
logic                     ignore_res;
logic                     ignore_res_p;

logic [DataWidth-1:0]     exp_res_w;
logic                     exp_res_p_w;
logic [4*DataWidth-1:0] exp_mult32_res;
logic                   cmp_res_p_w;
logic [DataWidth-1:0]   cmp_res_w;
logic                     ignore_res_w;
logic                     ignore_res_p_w;

logic [DataWidth-1:0]   op_a_w;
logic [DataWidth-1:0]   op_b_w;
logic [DataWidth-1:0]   op_c_w;
logic [DataWidth-1:0]   op_a_msb_w;
logic [DataWidth-1:0]   op_b_msb_w;
logic                  op_d_w;
logic fail, fail_latch;

localparam PE_ADD_OP         = 6'h0;
localparam PE_SUB_OP         = 6'h1;

localparam PE_ABS_OP         = 6'h3;

localparam PE_GTE_MAX_OP = 6'h4;
localparam PE_LTE_MIN_OP = 6'h5;
localparam PE_EQ_OP          = 6'h6;

localparam PE_SEL_OP         = 6'h8;

localparam PE_RSHFT_OP   = 6'hF;
localparam PE_RSHFT_S_OP = 6'h10;
localparam PE_LSHFT_OP   = 6'h11;

localparam PE_MULT_0_OP  = 6'hB;
localparam PE_MULT_1_OP  = 6'hC;
localparam PE_MULT_2_OP  = 6'hD;

localparam PE_OR_OP          = 6'h12;
localparam PE_AND_OP         = 6'h13;
localparam PE_XOR_OP         = 6'h14;
localparam PE_INV_OP         = 6'h15;

localparam PE_CNTR_OP        = 6'h18;

localparam PE_DIV_OP        = 6'h19;


always_ff @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        fail_latch <= 0;
    else if(fail)
        fail_latch <= 1;
end

assign fail_res     = ~ignore_res & (exp_res !== cmp_res);
assign fail_res_p = ~ignore_res_p & (exp_res_p !== cmp_res_p);

assign fail             = fail_res | fail_res_p;



typedef enum {
    Nop,
    RegA_load, RegB_load, RegC_load, RegD_load, RegE_load, RegF_load,
    RegA_bypass, RegA_valid, RegA_const, RegB_bypass, RegB_valid, RegB_const, Regfile_mode,
    Regfile0_load, Regfile1_load, Regfile2_load, Regfile3_load,
    Regfile0_read, Regfile1_read, Regfile2_read, Regfile3_read,
    Operation
} command;

command next_cmd;
command current_cmd;



typedef enum {
    Add_op, Sub_op, Abs_op, GteMax_op, LteMin_op, Eq_op,
    Sel_op, Rshft_op, RshftS_op, Lshft_op, Mult0_op, Mult1_op, Mult2_op, Or_op,
    And_op, Xor_op, Inv_op, Cntr_op, Div_op, Acc_op, InvalidOp
} oper;

oper next_op;
oper current_op;
logic is_signed_next;


task write_command;
    input [10:0] cmd;
    input [15:0] data;
    input sign;
    begin
        #(CLK_PERIOD/10);
        next_cmd = command'(cmd);
        if (next_cmd == Operation) begin
            next_op = oper'(data);
            is_signed_next = sign;
            op_a_w = $urandom_range(2**DataWidth - 1,0);
            op_b_w = {2{16'($urandom_range(31,0))}};
            op_c_w = $urandom_range(2**DataWidth - 1,0);
            op_a_msb_w = $urandom_range(2**DataWidth - 1,0);
            op_b_msb_w = $urandom_range(2**DataWidth - 1,0);
            op_d_w = $urandom_range(1,0);
        end
        else begin
            temp_data = data;
        end
        #(CLK_PERIOD*9/10);
    end
endtask



logic [2*DataWidth-1:0] mad_full;
assign mad_full = (data0_w*data1_w) + data2_w;
logic [DataWidth + 1: 0] full_sum;
assign full_sum = data0_w + data1_w + data2_w + bit0_w;

function [DataWidth-1:0] abs (input [DataWidth-1:0] a);
    abs = ($signed(a) < 0) ? -a : a;
endfunction

always_comb begin
    cfg_d_w = 'h0;
    cfg_a_w = 'h0;
    cfg_en_w = 'h0;
    data0_w = 'h0;
    data1_w = 'h0;
    data2_w = 'h0;
    bit0_w = 'h0;
    bit1_w = 'h0;
    bit2_w = 'h0;
    case(next_cmd)
        RegA_load : begin
            cfg_a_w = 8'hF0;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        RegB_load : begin
            cfg_a_w = 8'hF1;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        RegC_load : begin
            cfg_a_w = 8'hF2;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end




        RegA_const : begin
            cfg_a_w = 8'hFF;
            cfg_d_w[17:16] = 2'h0;
            cfg_en_w = 1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        RegB_const : begin
            cfg_a_w = 8'hFF;
            cfg_d_w[20:18] = 3'h0;
            cfg_en_w = 1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile_mode : begin
            cfg_a_w = 8'hFF;
            cfg_d_w[20:18] = 3'h4;
            cfg_en_w = 1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile0_load : begin
            cfg_a_w = 8'hF1;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile1_load : begin
            cfg_a_w = 8'hD0;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile2_load : begin
            cfg_a_w = 8'hD1;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile3_load : begin
            cfg_a_w = 8'hD2;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile0_read : begin
            data1_w = 16'h0;
            cfg_a_w = 8'hF1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile1_read : begin
            data1_w = 16'h1;
            cfg_a_w = 8'hD0;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile2_read : begin
            data1_w = 16'h2;
            cfg_a_w = 8'hD1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile3_read : begin
            data1_w = 16'h3;
            cfg_a_w = 8'hD2;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Operation : begin
            cfg_en_w = 1;
            cfg_a_w = 8'hFF;
            data0_w = op_a_w;
            data1_w = op_b_w;
            data2_w = op_c_w;
            data0_msb_w = op_a_msb_w;
            data1_msb_w = op_b_msb_w;
            bit0_w = op_d_w;
            cfg_d_w[9] = 0;
            case(next_op)
                Add_op : begin
                    cfg_d_w[5:0] = PE_ADD_OP;
                    exp_res_w          = full_sum[DataWidth-1:0];
                    exp_res_p_w        = |full_sum[DataWidth+1:DataWidth];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b0;
                end
                Sub_op : begin
                    cfg_d_w[5:0] = PE_SUB_OP;
                    exp_res_w          = (data0_w - data1_w) + data2_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Abs_op : begin
                    cfg_d_w[5:0] = PE_ABS_OP;
                    exp_res_w          = abs(data0_w - data1_w) + data2_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                GteMax_op : begin
                    cfg_d_w[5:0] = PE_GTE_MAX_OP;
                    if (is_signed_next) begin
                        exp_res_w          = ($signed(data0_w) >= $signed(data1_w)) ? data0_w : data1_w;
                        exp_res_p_w        = ($signed(data0_w) >= $signed(data1_w));
                    end else begin
                        exp_res_w          = (data0_w >= data1_w) ? data0_w : data1_w;
                        exp_res_p_w        = (data0_w >= data1_w);
                    end
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b0;
                end
                LteMin_op : begin
                    cfg_d_w[5:0] = PE_LTE_MIN_OP;
                    if (is_signed_next) begin
                        exp_res_w          = ($signed(data0_w) <= $signed(data1_w)) ? data0_w : data1_w;
                        exp_res_p_w        = ($signed(data0_w) <= $signed(data1_w));
                    end else begin
                        exp_res_w          = (data0_w <= data1_w) ? data0_w : data1_w;
                        exp_res_p_w        = (data0_w <= data1_w);
                    end
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b0;
                end
                Eq_op : begin
                    cfg_d_w[5:0] = PE_EQ_OP;
                    exp_res_p_w        = (data0_w === data1_w);
                    ignore_res_w   = 1'b1;
                    ignore_res_p_w = 1'b0;
                end
                Sel_op : begin
                    cfg_d_w[5:0] = PE_SEL_OP;
                    exp_res_w          = bit0_w ? data0_w : data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Lshft_op : begin
                    data1_w = {2{16'($urandom_range(16,0))}};
                    cfg_d_w[5:0] = PE_LSHFT_OP;
                    exp_res_w          = data0_w << data1_w[3:0];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                RshftS_op : begin
                    data1_w = {2{16'($urandom_range(16,0))}};
                    cfg_d_w[5:0] = PE_RSHFT_S_OP;
                    exp_res_w          = $signed(data0_w) >>> data1_w[3:0];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Rshft_op : begin
                    data1_w = {2{16'($urandom_range(16,0))}};
                    cfg_d_w[5:0] = PE_RSHFT_OP;
                    exp_res_w          = data0_w >> data1_w[3:0];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Or_op : begin
                    cfg_d_w[5:0] = PE_OR_OP;
                    exp_res_w          = data0_w | data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                And_op : begin
                    cfg_d_w[5:0] = PE_AND_OP;
                    exp_res_w          = data0_w & data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Xor_op : begin
                    cfg_d_w[5:0] = PE_XOR_OP;
                    exp_res_w          = data0_w ^ data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Inv_op : begin
                    cfg_d_w[5:0] = PE_INV_OP;
                    exp_res_w          = ~data0_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Mult0_op : begin
                    cfg_d_w[5:0] = PE_MULT_0_OP;
                    exp_res_w          = (data0_w*data1_w) + data2_w ;
                    exp_mult32_res = {data0_msb_w, data0_w} * {data1_msb_w, data1_w};
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Mult1_op : begin
                    cfg_d_w[5:0] = PE_MULT_1_OP;
                    exp_res_w          = (mad_full >> (DataWidth/2));
                    exp_mult32_res = {data0_msb_w, data0_w} * {data1_msb_w, data1_w};
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Mult2_op : begin
                    cfg_d_w[5:0] = PE_MULT_2_OP;
                    exp_res_w          = (mad_full >> DataWidth);
                    exp_mult32_res = {data0_msb_w, data0_w} * {data1_msb_w, data1_w};
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Cntr_op : begin
                    cfg_d_w[5:0] = PE_CNTR_OP;
                    exp_res_w          = 'hX;
                    ignore_res_w   = 1'b1;
                    ignore_res_p_w = 1'b1;
                    data0_w = 'h1;
                    data1_w = 'h0;
                    data2_w = 'h9;
                end

                Div_op : begin
                    cfg_d_w[5:0] = PE_DIV_OP;
                    exp_res_w          = 'hX;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                    data0_w = 'h1234;
                    data1_w = 'h56;
                    data2_w = 'h0;
                end

                default: begin
                    $display("Error: unexpected instruction op code: %x!\n", next_op);
                end
            endcase
        end
        default : begin
            cfg_d_w = 'h0;
            cfg_a_w = 'h0;
            cfg_en_w = 'h0;
            data0_w = 'h0;
            data1_w = 'h0;
            data2_w = 'h0;
            bit0_w = 'h0;
            bit1_w = 'h0;
            bit2_w = 'h0;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
    endcase
end


always_ff @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        cfg_d <= 'h0;
        cfg_a <= 'h0;
        cfg_en <= 'h0;
        data0 <= 'h0;
        data1 <= 'h0;
        data2 <= 'h0;
        bit0 <= 'h0;
        bit1 <= 'h0;
        bit2 <= 'h0;
        exp_res <= 'h0;
        exp_res_next <= 'h0;
        exp_res_p <= 'h0;
        exp_res_p_next <= 'h0;
        cmp_res <= 'h0;
        ignore_res <= 'h0;
        ignore_res_p <= 'h0;
        current_cmd <= Nop;
    end
    else begin
        cfg_d <= cfg_d_w;
        cfg_a <= cfg_a_w;
        cfg_en <= cfg_en_w;
        data0 <= data0_w;
        data1 <= data1_w;
        data2 <= data2_w;
        bit0 <= bit0_w;
        bit1 <= bit1_w;
        bit2 <= bit2_w;
        exp_res_next <= exp_res_w;
        exp_res <= exp_res_next;
        exp_res_p_next <= exp_res_p_w;
        exp_res_p <= exp_res_p_next;
        cmp_res <= cmp_res_w;
        ignore_res <= ignore_res_w;
        ignore_res_p <= ignore_res_p_w;
        current_cmd <= next_cmd;
    end
end





initial begin
    #1000000 $display("Time = %d clk = %b", $time, clk);

    if(fail_latch)
        $display("\nAt least one test has FAILED!\n");
    else
        $display("\nAll tests Passed\n");

     $finish;
end

initial begin
    clk = 0;
    forever begin
    #(CLK_PERIOD/2) clk = ~clk;
    end
end

initial begin
    rst_n = 0;
    repeat(10) @(posedge clk);
    rst_n = 1;
end

initial begin
    repeat(20) @(posedge clk);
    write_command(RegA_load, 16'h1234, 1);
    write_command(RegB_load, 16'h1, 1);
    write_command(Regfile0_load, 16'hC0, 1);
    write_command(Regfile1_load, 16'hC1, 1);
    write_command(Regfile2_load, 16'hC2, 1);
    write_command(Regfile3_load, 16'hC3, 1);
    write_command(Regfile_mode, 16'h0, 1);
    write_command(Regfile0_read, 16'h0, 1);
    write_command(Regfile1_read, 16'h0, 1);
    write_command(Regfile2_read, 16'h0, 1);
    write_command(Regfile3_read, 16'h0, 1);
    write_command(RegA_const, 16'h0, 1);
    write_command(RegB_const, 16'h0, 1);
    write_command(RegA_load, 16'h1, 1);
    write_command(RegB_load, 16'h0, 1);
    write_command(RegC_load, 16'h9, 1);
    write_command(Operation, Add_op, 1);
    write_command(Operation, Cntr_op, 1);
end

test_pe_unq1  dut (
    .clk (clk),
    .rst_n (rst_n),
    .clk_en (1'b1),
    .cfg_d (cfg_d),
    .cfg_a (cfg_a),
    .cfg_en (cfg_en),
    .data0 (data0),
    .data1 (data1),
    .data2 (data2),
    .bit0 (bit0),
    .bit1 (bit1),
    .bit2 (bit2),

    .res     (res),
    .irq (),
    .res_p (res_p),
    .read_data (read_data)
);

endmodule
module  `mname()`;


localparam DataWidth = 16;

logic                   clk;
logic                   clk_en;
logic                   rst_n;

logic [2*DataWidth-1:0]       cfg_d;
logic [7:0]             cfg_a;
logic                   cfg_en;
logic [DataWidth-1:0]       data0;
logic [DataWidth-1:0]       data1;
logic [DataWidth-1:0]       data2;
logic                   bit0;
logic                   bit1;
logic                   bit2;
logic [DataWidth-1:0]       res;
logic                   res_p;
logic [DataWidth-1:0]       read_data;
logic [DataWidth-1:0]       temp_data;

logic [2*DataWidth-1:0]       cfg_d_w;
logic [7:0]             cfg_a_w;
logic                   cfg_en_w;
logic [DataWidth-1:0]       data0_w;
logic [DataWidth-1:0]       data1_w;
logic [DataWidth-1:0]       data2_w;
logic [DataWidth-1:0]       data0_msb_w;
logic [DataWidth-1:0]       data1_msb_w;
logic                   bit0_w;
logic                   bit1_w;
logic                   bit2_w;
logic [DataWidth-1:0]     exp_res;
logic                     exp_res_p;
logic [DataWidth-1:0]     exp_res_next;
logic                     exp_res_p_next;
logic [DataWidth-1:0]   cmp_res;
logic                   cmp_res_p;
logic                     ignore_res;
logic                     ignore_res_p;

logic [DataWidth-1:0]     exp_res_w;
logic                     exp_res_p_w;
logic [4*DataWidth-1:0] exp_mult32_res;
logic                   cmp_res_p_w;
logic [DataWidth-1:0]   cmp_res_w;
logic                     ignore_res_w;
logic                     ignore_res_p_w;

logic [DataWidth-1:0]   op_a_w;
logic [DataWidth-1:0]   op_b_w;
logic [DataWidth-1:0]   op_c_w;
logic [DataWidth-1:0]   op_a_msb_w;
logic [DataWidth-1:0]   op_b_msb_w;
logic                  op_d_w;
logic fail, fail_latch;

localparam PE_ADD_OP         = 6'h0;
localparam PE_SUB_OP         = 6'h1;

localparam PE_ABS_OP         = 6'h3;

localparam PE_GTE_MAX_OP = 6'h4;
localparam PE_LTE_MIN_OP = 6'h5;
localparam PE_EQ_OP          = 6'h6;

localparam PE_SEL_OP         = 6'h8;

localparam PE_RSHFT_OP   = 6'hF;
localparam PE_RSHFT_S_OP = 6'h10;
localparam PE_LSHFT_OP   = 6'h11;

localparam PE_MULT_0_OP  = 6'hB;
localparam PE_MULT_1_OP  = 6'hC;
localparam PE_MULT_2_OP  = 6'hD;

localparam PE_OR_OP          = 6'h12;
localparam PE_AND_OP         = 6'h13;
localparam PE_XOR_OP         = 6'h14;
localparam PE_INV_OP         = 6'h15;

localparam PE_CNTR_OP        = 6'h18;

localparam PE_DIV_OP        = 6'h19;


always_ff @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        fail_latch <= 0;
    else if(fail)
        fail_latch <= 1;
end

assign fail_res     = ~ignore_res & (exp_res !== cmp_res);
assign fail_res_p = ~ignore_res_p & (exp_res_p !== cmp_res_p);

assign fail             = fail_res | fail_res_p;



typedef enum {
    Nop,
    RegA_load, RegB_load, RegC_load, RegD_load, RegE_load, RegF_load,
    RegA_bypass, RegA_valid, RegA_const, RegB_bypass, RegB_valid, RegB_const, Regfile_mode,
    Regfile0_load, Regfile1_load, Regfile2_load, Regfile3_load,
    Regfile0_read, Regfile1_read, Regfile2_read, Regfile3_read,
    Operation
} command;

command next_cmd;
command current_cmd;



typedef enum {
    Add_op, Sub_op, Abs_op, GteMax_op, LteMin_op, Eq_op,
    Sel_op, Rshft_op, RshftS_op, Lshft_op, Mult0_op, Mult1_op, Mult2_op, Or_op,
    And_op, Xor_op, Inv_op, Cntr_op, Div_op, Acc_op, InvalidOp
} oper;

oper next_op;
oper current_op;
logic is_signed_next;


task write_command;
    input [10:0] cmd;
    input [15:0] data;
    input sign;
    begin
        #(CLK_PERIOD/10);
        next_cmd = command'(cmd);
        if (next_cmd == Operation) begin
            next_op = oper'(data);
            is_signed_next = sign;
            op_a_w = $urandom_range(2**DataWidth - 1,0);
            op_b_w = {2{16'($urandom_range(31,0))}};
            op_c_w = $urandom_range(2**DataWidth - 1,0);
            op_a_msb_w = $urandom_range(2**DataWidth - 1,0);
            op_b_msb_w = $urandom_range(2**DataWidth - 1,0);
            op_d_w = $urandom_range(1,0);
        end
        else begin
            temp_data = data;
        end
        #(CLK_PERIOD*9/10);
    end
endtask



logic [2*DataWidth-1:0] mad_full;
assign mad_full = (data0_w*data1_w) + data2_w;
logic [DataWidth + 1: 0] full_sum;
assign full_sum = data0_w + data1_w + data2_w + bit0_w;

function [DataWidth-1:0] abs (input [DataWidth-1:0] a);
    abs = ($signed(a) < 0) ? -a : a;
endfunction

always_comb begin
    cfg_d_w = 'h0;
    cfg_a_w = 'h0;
    cfg_en_w = 'h0;
    data0_w = 'h0;
    data1_w = 'h0;
    data2_w = 'h0;
    bit0_w = 'h0;
    bit1_w = 'h0;
    bit2_w = 'h0;
    case(next_cmd)
        RegA_load : begin
            cfg_a_w = 8'hF0;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        RegB_load : begin
            cfg_a_w = 8'hF1;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        RegC_load : begin
            cfg_a_w = 8'hF2;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end




        RegA_const : begin
            cfg_a_w = 8'hFF;
            cfg_d_w[17:16] = 2'h0;
            cfg_en_w = 1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        RegB_const : begin
            cfg_a_w = 8'hFF;
            cfg_d_w[20:18] = 3'h0;
            cfg_en_w = 1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile_mode : begin
            cfg_a_w = 8'hFF;
            cfg_d_w[20:18] = 3'h4;
            cfg_en_w = 1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile0_load : begin
            cfg_a_w = 8'hF1;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile1_load : begin
            cfg_a_w = 8'hD0;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile2_load : begin
            cfg_a_w = 8'hD1;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile3_load : begin
            cfg_a_w = 8'hD2;
            cfg_d_w[15:0] = temp_data;
            cfg_en_w = 1;
            exp_res_w = temp_data;
            cmp_res_w = read_data;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile0_read : begin
            data1_w = 16'h0;
            cfg_a_w = 8'hF1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile1_read : begin
            data1_w = 16'h1;
            cfg_a_w = 8'hD0;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile2_read : begin
            data1_w = 16'h2;
            cfg_a_w = 8'hD1;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Regfile3_read : begin
            data1_w = 16'h3;
            cfg_a_w = 8'hD2;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
        Operation : begin
            cfg_en_w = 1;
            cfg_a_w = 8'hFF;
            data0_w = op_a_w;
            data1_w = op_b_w;
            data2_w = op_c_w;
            data0_msb_w = op_a_msb_w;
            data1_msb_w = op_b_msb_w;
            bit0_w = op_d_w;
            cfg_d_w[9] = 0;
            case(next_op)
                Add_op : begin
                    cfg_d_w[5:0] = PE_ADD_OP;
                    exp_res_w          = full_sum[DataWidth-1:0];
                    exp_res_p_w        = |full_sum[DataWidth+1:DataWidth];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b0;
                end
                Sub_op : begin
                    cfg_d_w[5:0] = PE_SUB_OP;
                    exp_res_w          = (data0_w - data1_w) + data2_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Abs_op : begin
                    cfg_d_w[5:0] = PE_ABS_OP;
                    exp_res_w          = abs(data0_w - data1_w) + data2_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                GteMax_op : begin
                    cfg_d_w[5:0] = PE_GTE_MAX_OP;
                    if (is_signed_next) begin
                        exp_res_w          = ($signed(data0_w) >= $signed(data1_w)) ? data0_w : data1_w;
                        exp_res_p_w        = ($signed(data0_w) >= $signed(data1_w));
                    end else begin
                        exp_res_w          = (data0_w >= data1_w) ? data0_w : data1_w;
                        exp_res_p_w        = (data0_w >= data1_w);
                    end
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b0;
                end
                LteMin_op : begin
                    cfg_d_w[5:0] = PE_LTE_MIN_OP;
                    if (is_signed_next) begin
                        exp_res_w          = ($signed(data0_w) <= $signed(data1_w)) ? data0_w : data1_w;
                        exp_res_p_w        = ($signed(data0_w) <= $signed(data1_w));
                    end else begin
                        exp_res_w          = (data0_w <= data1_w) ? data0_w : data1_w;
                        exp_res_p_w        = (data0_w <= data1_w);
                    end
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b0;
                end
                Eq_op : begin
                    cfg_d_w[5:0] = PE_EQ_OP;
                    exp_res_p_w        = (data0_w === data1_w);
                    ignore_res_w   = 1'b1;
                    ignore_res_p_w = 1'b0;
                end
                Sel_op : begin
                    cfg_d_w[5:0] = PE_SEL_OP;
                    exp_res_w          = bit0_w ? data0_w : data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Lshft_op : begin
                    data1_w = {2{16'($urandom_range(16,0))}};
                    cfg_d_w[5:0] = PE_LSHFT_OP;
                    exp_res_w          = data0_w << data1_w[3:0];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                RshftS_op : begin
                    data1_w = {2{16'($urandom_range(16,0))}};
                    cfg_d_w[5:0] = PE_RSHFT_S_OP;
                    exp_res_w          = $signed(data0_w) >>> data1_w[3:0];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Rshft_op : begin
                    data1_w = {2{16'($urandom_range(16,0))}};
                    cfg_d_w[5:0] = PE_RSHFT_OP;
                    exp_res_w          = data0_w >> data1_w[3:0];
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Or_op : begin
                    cfg_d_w[5:0] = PE_OR_OP;
                    exp_res_w          = data0_w | data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                And_op : begin
                    cfg_d_w[5:0] = PE_AND_OP;
                    exp_res_w          = data0_w & data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Xor_op : begin
                    cfg_d_w[5:0] = PE_XOR_OP;
                    exp_res_w          = data0_w ^ data1_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Inv_op : begin
                    cfg_d_w[5:0] = PE_INV_OP;
                    exp_res_w          = ~data0_w;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Mult0_op : begin
                    cfg_d_w[5:0] = PE_MULT_0_OP;
                    exp_res_w          = (data0_w*data1_w) + data2_w ;
                    exp_mult32_res = {data0_msb_w, data0_w} * {data1_msb_w, data1_w};
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Mult1_op : begin
                    cfg_d_w[5:0] = PE_MULT_1_OP;
                    exp_res_w          = (mad_full >> (DataWidth/2));
                    exp_mult32_res = {data0_msb_w, data0_w} * {data1_msb_w, data1_w};
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Mult2_op : begin
                    cfg_d_w[5:0] = PE_MULT_2_OP;
                    exp_res_w          = (mad_full >> DataWidth);
                    exp_mult32_res = {data0_msb_w, data0_w} * {data1_msb_w, data1_w};
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                end
                Cntr_op : begin
                    cfg_d_w[5:0] = PE_CNTR_OP;
                    exp_res_w          = 'hX;
                    ignore_res_w   = 1'b1;
                    ignore_res_p_w = 1'b1;
                    data0_w = 'h1;
                    data1_w = 'h0;
                    data2_w = 'h9;
                end

                Div_op : begin
                    cfg_d_w[5:0] = PE_DIV_OP;
                    exp_res_w          = 'hX;
                    ignore_res_w   = 1'b0;
                    ignore_res_p_w = 1'b1;
                    data0_w = 'h1234;
                    data1_w = 'h56;
                    data2_w = 'h0;
                end

                default: begin
                    $display("Error: unexpected instruction op code: %x!\n", next_op);
                end
            endcase
        end
        default : begin
            cfg_d_w = 'h0;
            cfg_a_w = 'h0;
            cfg_en_w = 'h0;
            data0_w = 'h0;
            data1_w = 'h0;
            data2_w = 'h0;
            bit0_w = 'h0;
            bit1_w = 'h0;
            bit2_w = 'h0;
            ignore_res_w = 1'b1;
            ignore_res_p_w = 1'b1;
        end
    endcase
end


always_ff @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        cfg_d <= 'h0;
        cfg_a <= 'h0;
        cfg_en <= 'h0;
        data0 <= 'h0;
        data1 <= 'h0;
        data2 <= 'h0;
        bit0 <= 'h0;
        bit1 <= 'h0;
        bit2 <= 'h0;
        exp_res <= 'h0;
        exp_res_next <= 'h0;
        exp_res_p <= 'h0;
        exp_res_p_next <= 'h0;
        cmp_res <= 'h0;
        ignore_res <= 'h0;
        ignore_res_p <= 'h0;
        current_cmd <= Nop;
    end
    else begin
        cfg_d <= cfg_d_w;
        cfg_a <= cfg_a_w;
        cfg_en <= cfg_en_w;
        data0 <= data0_w;
        data1 <= data1_w;
        data2 <= data2_w;
        bit0 <= bit0_w;
        bit1 <= bit1_w;
        bit2 <= bit2_w;
        exp_res_next <= exp_res_w;
        exp_res <= exp_res_next;
        exp_res_p_next <= exp_res_p_w;
        exp_res_p <= exp_res_p_next;
        cmp_res <= cmp_res_w;
        ignore_res <= ignore_res_w;
        ignore_res_p <= ignore_res_p_w;
        current_cmd <= next_cmd;
    end
end





initial begin
    #1000000 $display("Time = %d clk = %b", $time, clk);

    if(fail_latch)
        $display("\nAt least one test has FAILED!\n");
    else
        $display("\nAll tests Passed\n");

     $finish;
end

initial begin
    clk = 0;
    forever begin
    #(CLK_PERIOD/2) clk = ~clk;
    end
end

initial begin
    rst_n = 0;
    repeat(10) @(posedge clk);
    rst_n = 1;
end

initial begin
    repeat(20) @(posedge clk);
    write_command(RegA_load, 16'h1234, 1);
    write_command(RegB_load, 16'h1, 1);
    write_command(Regfile0_load, 16'hC0, 1);
    write_command(Regfile1_load, 16'hC1, 1);
    write_command(Regfile2_load, 16'hC2, 1);
    write_command(Regfile3_load, 16'hC3, 1);
    write_command(Regfile_mode, 16'h0, 1);
    write_command(Regfile0_read, 16'h0, 1);
    write_command(Regfile1_read, 16'h0, 1);
    write_command(Regfile2_read, 16'h0, 1);
    write_command(Regfile3_read, 16'h0, 1);
    write_command(RegA_const, 16'h0, 1);
    write_command(RegB_const, 16'h0, 1);
    write_command(RegA_load, 16'h1, 1);
    write_command(RegB_load, 16'h0, 1);
    write_command(RegC_load, 16'h9, 1);
    write_command(Operation, Add_op, 1);
    write_command(Operation, Cntr_op, 1);
end

test_pe_unq1  dut (
    .clk (clk),
    .rst_n (rst_n),
    .clk_en (1'b1),
    .cfg_d (cfg_d),
    .cfg_a (cfg_a),
    .cfg_en (cfg_en),
    .data0 (data0),
    .data1 (data1),
    .data2 (data2),
    .bit0 (bit0),
    .bit1 (bit1),
    .bit2 (bit2),

    .res     (res),
    .irq (),
    .res_p (res_p),
    .read_data (read_data)
);

endmodule