Search code examples
veriloghardwarefpgavivado

Vivado just points out that there is an exception


I'm trying to write a module which performs convolution on 24 by 24 bitmap image.

And here is the DUT and testbench.

Maybe there are some problems and I spend couple of hours to find what is problem but I can't figure it out.

Additionally, RTL Anaylsis works well without any error which makes me think that there is no problem on DUT.

Is there anyone who can help me?

module top_conv(clk,resetn,start,load_image_0,load_image_1,load_image_2,done,result);

    input clk,resetn,load_image_0,load_image_1,load_image_2,start;
    output done,result;

    reg [1:0] st;
    reg [1:0] nst;

    reg [7:0] input_buffer_0 [0:2];
    reg [7:0] input_buffer_1 [0:2];
    reg [7:0] input_buffer_2 [0:2];

    wire [7:0] load_image_0;
    wire [7:0] load_image_1;
    wire [7:0] load_image_2;

    reg [7:0] result;

    reg done;

    integer load_cnt, row_cnt, col_cnt , result_cnt ;

    parameter IDLE = 2'b00, LOAD = 2'b01, MAC = 2'b10, DONE = 2'b11;

    always@(posedge clk or negedge resetn)begin
        case(st)
            LOAD:begin
                input_buffer_0[load_cnt] <= load_image_0;
                input_buffer_1[load_cnt] <= load_image_1;
                input_buffer_2[load_cnt] <= load_image_2;
            end
            MAC:begin
                input_buffer_0[0] <= input_buffer_0[1];
                input_buffer_1[0] <= input_buffer_1[1];
                input_buffer_2[0] <= input_buffer_2[1];

                input_buffer_0[1] <= input_buffer_0[2];
                input_buffer_1[1] <= input_buffer_0[2];
                input_buffer_2[1] <= input_buffer_0[2];

                input_buffer_0[2] <= load_image_0;
                input_buffer_1[2] <= load_image_1;
                input_buffer_2[2] <= load_image_2;
            end
        endcase
    end

    always@(posedge clk or negedge resetn)begin
        if(!resetn) load_cnt <= 0;
        else if(st == LOAD) load_cnt <= load_cnt + 1;
        else load_cnt <= 0;
    end

    always@(posedge clk or negedge resetn)begin
        if(!resetn) begin
            col_cnt <= 0;
            row_cnt <= 0;
        end
        else if(st == MAC) begin
            if(col_cnt == 21) begin
                col_cnt <= 0;
                row_cnt <= row_cnt +1;
            end
        end
        else begin
            col_cnt <= 0;
            row_cnt <= 0;
        end
    end

    always@(posedge clk or negedge resetn)begin
        if( st == MAC ) begin
            result <= (input_buffer_0[0] + 2*input_buffer_0[1] + input_buffer_0[2])/16 + (input_buffer_1[0] + 2*input_buffer_1[1] + input_buffer_1[2])/8 + (input_buffer_2[0] + 2*input_buffer_2[1] + input_buffer_2[2])/16;
            done <= 1'b1;
        end
        else done <=1'b0;
    end

    always@(posedge clk or negedge resetn)begin
       if(!resetn) st <= 0;
       else st <= nst; 
    end

    always@(*)begin
        case(st)
            IDLE:begin
                if(start) nst = LOAD;
                else nst = IDLE;
            end
            LOAD:begin
                if(load_cnt == 2)nst = MAC;
                else nst = LOAD;
            end
            MAC:begin
                if((row_cnt == 21)&&(col_cnt == 21)) nst = DONE;
                else if(col_cnt == 21) nst = LOAD;
                else nst = MAC;
            end
            DONE:begin
                nst = IDLE;
            end
        endcase
    end    

endmodule

module testbench;

    reg clk,resetn,start;
    reg[7:0] val;
    reg [7:0] b_load_image_0,g_load_image_0,r_load_image_0;
    reg [7:0] b_load_image_1,g_load_image_1,r_load_image_1;
    reg [7:0] b_load_image_2,g_load_image_2,r_load_image_2;
    wire [2:0] done;
    wire [7:0] b_result,g_result,r_result;
    integer index;

    top_conv blue_result (clk,resetn,start,b_load_image_0,b_load_image_1,b_load_image_2,done[0],b_result);
    top_conv green_result (clk,resetn,start,g_load_image_0,g_load_image_1,g_load_image_2,done[1],g_result);
    top_conv red_result (clk,resetn,start,r_load_image_0,r_load_image_1,r_load_image_2,done[2],r_result);


    parameter read_fileName1 = "D:/blur_filter_unit/test.bmp" ;

    localparam ARRAY_LEN = 24*24*3 + 54;

    reg [7:0] data1 [0:ARRAY_LEN-1];

    integer size,start_pos,width,height,bitcount;

    task readBMP;
            integer fileID1;
        begin
            fileID1 = $fopen(read_fileName1, "rb");
            $display("%d" ,fileID1);

            if(fileID1 == 0) begin
                $display("Error: please check file path");
                $finish;
            end 
            else begin
                $fread(data1, fileID1);
                $fclose(fileID1);

                size = {data1[5],data1[4],data1[3],data1[2]};
                $display("size - %d", size);
                start_pos = {data1[13],data1[12],data1[11],data1[10]};
                $display("startpos : %d", start_pos);
                width = {data1[21],data1[20],data1[19],data1[18]};
                height = {data1[25],data1[24],data1[23],data1[22]};
                $display("width - %d; height - %d",width,height);

                bitcount = {data1[29],data1[28]};

                if(bitcount != 24) begin
                    $display("Error: Please check the image file. It may be corrupted");
                end

                if(width%4)begin
                    $display("width is not suitable");
                    $finish;
                end
            end
        end
    endtask

    integer i,j;
    localparam RESULT_ARRAY_LEN = 24*24*3;

    reg[7:0] result[0:RESULT_ARRAY_LEN - 1];

    always @(posedge clk or negedge resetn)begin
        if(!resetn)begin
            j <= 8'b0;
        end
        else begin
            if(&done[2:0]) begin
                result[j] <= b_result;
                result[j+1] <= g_result;
                result[j+2] <= r_result;
                j <= j+3;
            end
        end
    end

    parameter write_fileName1 = "D:/blur_filter_unit/result.bmp";

    task writeBMP;
            integer fileID, k;
        begin
            fileID = $fopen(write_fileName1,"wb");

            for(k = 0; k < start_pos; k=k+1)begin
                $fwrite(fileID, "%c",data1[k]);
            end

            for(k = start_pos; k<size; k=k+1)begin
                $fwrite(fileID,"%c",result[k-start_pos]);
            end    

            $fclose(fileID);
            $display("Result.bmp is generated \n");
        end
    endtask

    always begin
        #1 clk = ~clk;
    end

    initial begin
        clk = 1;
        resetn = 0;
        start = 0;
        index = 1;

        b_load_image_0 = 0;
        g_load_image_0 = 0;
        r_load_image_0 = 0;
        b_load_image_1 = 0;
        g_load_image_1 = 0;
        r_load_image_1 = 0;
        b_load_image_2 = 0;
        g_load_image_2 = 0;
        r_load_image_2 = 0;

        readBMP;

        #10;

        resetn = 1;
        start = 1;

        for(i = start_pos; i<size; i=i+3)begin
            {r_load_image_0, r_load_image_1, r_load_image_2} ={data1[i+2],data1[i+2+width*3],data1[i+2+width*6]};
            {g_load_image_0, g_load_image_1, g_load_image_2} = {data1[i+1],data1[i+1+width*3],data1[i+1+width*6]};
            {b_load_image_0, b_load_image_1, b_load_image_2} = {data1[i],data1[i+width*3],data1[i+width*6]};
            #1;
        end

        #10;
        #writeBMP;

        #10
        $stop;
    end


endmodule

Solution

  • Even though this is not a complete answer, for figuring out the error you can use the below code which is revised version of your code for ease of debugging.

    i think when synthesizing your design you might have faced this issue Due to line numbers 25 & 71 in your code.You are declaring edge sensitive signal in sensitivity list and u are not using it in the always block. so tool cannot understand how to map it and throwing an error.

    module top_conv(
         input            clk,resetn,start,
         input      [7:0] load_image_0,load_image_1,load_image_2,
         output reg       done,
         output reg [7:0] result
     );
    
        reg [7:0] input_buffer_0 [0:2];
        reg [7:0] input_buffer_1 [0:2];
        reg [7:0] input_buffer_2 [0:2];
    
        reg [4:0] row_cnt, col_cnt;
        reg [1:0] load_cnt;
    
        parameter IDLE = 2'b00,
                  LOAD = 2'b01,
                  MAC  = 2'b10,
                  DONE = 2'b11;
    
       reg [1:0] state,next;
    
         always@(posedge clk or negedge resetn)begin
           if(!resetn) state <= #10 IDLE ;
           else        state <= #10 next ;
        end
    
        always@(*)begin
                      next = 'bx; // default undefined state
            case(state)
                IDLE: next =           start ? LOAD : IDLE ;
                LOAD: next = (load_cnt == 2) ? MAC  : LOAD ;
                MAC : next = ((row_cnt == 21)&&(col_cnt == 21)) ? DONE :
                                               (col_cnt == 21)  ? LOAD : MAC ;
                DONE: next = IDLE ;
            endcase
        end
    
        always@(posedge clk or negedge resetn)begin
            if(!resetn) begin
               col_cnt  <= #10 0;
               row_cnt  <= #10 0;
               load_cnt <= #10 0;
               done     <= #10 1'b0;
               result   <= #10 0;
            end else begin 
               col_cnt  <= #10 0;
               row_cnt  <= #10 0;
               load_cnt <= #10 0;
               done     <= #10 1'b0;
               result   <= #10 0;
            case(next)
               LOAD:load_cnt <= #10 load_cnt + 1'b1 ;
               MAC :begin
                    col_cnt  <= #10 (col_cnt == 21) ? 0       : col_cnt + 1'b1 ;
                    row_cnt  <= #10 (col_cnt == 21) ? row_cnt : row_cnt + 1'b1 ;
                end          
               DONE:begin
                      result <= #10 (input_buffer_0[0] + 2*input_buffer_0[1] + input_buffer_0[2])/16 +
                                    (input_buffer_1[0] + 2*input_buffer_1[1] + input_buffer_1[2])/8  +
                                    (input_buffer_2[0] + 2*input_buffer_2[1] + input_buffer_2[2])/16 ;
                      done   <= #10 1'b1;
                end
            endcase
          end
        end
    
       always@(posedge clk)begin
        case(next)
            LOAD:begin
                input_buffer_0[load_cnt] <= #10 load_image_0;
                input_buffer_1[load_cnt] <= #10 load_image_1;
                input_buffer_2[load_cnt] <= #10 load_image_2;
            end
            MAC:begin
                input_buffer_0[0] <= #10 input_buffer_0[1];
                input_buffer_1[0] <= #10 input_buffer_1[1];
                input_buffer_2[0] <= #10 input_buffer_2[1];
    
                input_buffer_0[1] <= #10 input_buffer_0[2];
                input_buffer_1[1] <= #10 input_buffer_0[2];
                input_buffer_2[1] <= #10 input_buffer_0[2];
    
                input_buffer_0[2] <= #10 load_image_0;
                input_buffer_1[2] <= #10 load_image_1;
                input_buffer_2[2] <= #10 load_image_2;
            end
        endcase
       end
    
    endmodule