Вивадо просто указывает, что есть исключение - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь написать модуль, который выполняет свертку на растровом изображении 24 на 24.

А вот DUT и testbench.

Возможно, есть некоторые проблемы, и я провожу пару часов, чтобы найти, в чем проблема, но я не могу понять.

Кроме того, RTL Anaylsis работает хорошо без каких-либо ошибок, что заставляет меня думать, что на DUT проблем нет.

есть кто-нибудь, кто может мне помочь?

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

1 Ответ

2 голосов
/ 03 марта 2020

Несмотря на то, что это не полный ответ, для выяснения ошибки вы можете использовать приведенный ниже код, который является пересмотренной версией вашего кода для простоты отладки.

Я думаю, что при синтезировании вашего дизайна вы можете иметь столкнулся с этой проблемой Из-за номеров строк 25 и 71 в вашем коде. Вы объявляете сигнал, чувствительный к фронту, в списке чувствительности, и вы не используете его в блоке Always . поэтому инструмент не может понять, как отобразить его и выдать ошибку.

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
...