在使用generate块时无法进行综合

编程语言 2026-07-10

我正在做一个项目,使用Basys-3的 VGA端口绘制正方形(最终目标是一个Etch-a-Sketch风格的设备,但一步步来,目前VGA控制器已经创建并经过测试可以工作)。

正如我的代码注释所示,每个正方形是由其左上角像素的位置定义的。我想使用一个 generate 块来实现,这样就不会那么吃力,未来也更易扩展。

但在尝试综合项目时,日志会卡在“finished applying XDC constraints”这条信息处。我已经让它保持这种状态长达2 小时。我之前使用generate块创建时钟分频器来产生多个触发器(https://digilent.com/reference/learn/programmable-logic/tutorials/use-flip-flops-to-build-a-clock-divider/start)。

-----编辑----- 在请求创建一个完整模块用于测试之后,我编写了以下代码。一个模块用于运行仿真,另一个模块用于保存原问题中的主逻辑。在这个过程中以及我自己测试时,我发现这条信息 "variable 'squareTopLeftTemp[1]' might have multiple concurrent drivers" 出现了多次。我将继续研究这个问题,但如果再得到帮助就太棒了!

----- 新代码,完整模块 -----

// For simulating my testing module & checking print statements module tb_testing( );

reg in;

testing t (in);

initial begin

    in = 0;

    in = 1;

end

endmodule

module testing (input in);

parameter n = 5;
parameter blockSize = 20;

parameter rowStartCol = 144;
parameter colStartRow = 35;

// for calculation within generate block
reg[9:0] squareTopLeftTemp [1:0];

reg [9:0] square[n:0][n:0][1:0];

// working code starts here:
/*
assign square[0][0][0] = 144;
assign square[0][0][1] = 35;

assign square[0][1][0] = 144;
assign square[0][1][1] = 55;

assign square[0][2][0] = 144;
assign square[0][2][1] = 75;

assign square[0][3][0] = 144;
assign square[0][3][1] = 95;

assign square[0][4][0] = 144;
assign square[0][4][1] = 115;

assign square[0][5][0] = 144;
assign square[0][5][1] = 135;

assign square[1][0][0] = 164;
assign square[1][0][1] = 35;

assign square[1][1][0] =  164;
assign square[1][1][1] = 55;

assign square[1][2][0] =  164;
assign square[1][2][1] = 75;

assign square[1][3][0] =  164;
assign square[1][3][1] = 95;

assign square[1][4][0] =  164;
assign square[1][4][1] = 115;

assign square[1][5][0] =  164;
assign square[1][5][1] = 135;

assign square[2][0][0] = 184;
assign square[2][0][1] = 35;

assign square[2][1][0] =  184;
assign square[2][1][1] = 55;

assign square[2][2][0] =  184;
assign square[2][2][1] = 75;

assign square[2][3][0] =  184;
assign square[2][3][1] = 95;

assign square[2][4][0] =  184;
assign square[2][4][1] = 115;

assign square[2][5][0] =  184;
assign square[2][5][1] = 135;
//
assign square[4][0][0] = 204;
assign square[4][0][1] =35;

assign square[4][1][0] =  204;
assign square[4][1][1] =55;

assign square[4][2][0] =  204;
assign square[4][2][1] =75;

assign square[4][3][0] =  204;
assign square[4][3][1] =95;

assign square[4][4][0] =  204;
assign square[4][4][1] =115;

assign square[4][5][0] =  204;
assign square[4][5][1] =135;
//
// somehow missing row 3 but that is okay for proof of working   
//    
assign square[5][0][0] = 224;
assign square[5][0][1] =35;

assign square[5][1][0] =  224;
assign square[5][1][1] =55;

assign square[5][2][0] =  224;
assign square[5][2][1] =75;

assign square[5][3][0] =  224;
assign square[5][3][1] =95;

assign square[5][4][0] =  224;
assign square[5][4][1] =115;

assign square[5][5][0] =  224;
assign square[5][5][1] =135;

*/

// non-working code starts here   

genvar i;
genvar j;

reg [9:0] currentCol; // starts at 144
reg [9:0] currentRow; // starts at 35
assign squareTopLeftTemp[0] = rowStartCol;
assign squareTopLeftTemp[1] = colStartRow;

generate
    for (i = 0 ; i <= n ; i = i + 1) begin
        for (j = 0 ; j <= n; j = j + 1) begin

            // create a row of squares, columns are added, [1]
            assign square[i][j][0] = squareTopLeftTemp[0];
            assign square[i][j][1] = squareTopLeftTemp[1];

            //increment column
            assign squareTopLeftTemp[1] = squareTopLeftTemp[1]+blockSize;
            // save inputs for use on next iteration
            assign currentCol = squareTopLeftTemp[0];
            assign currentRow = squareTopLeftTemp[1];
            assign squareTopLeftTemp[0] = currentCol;
            assign squareTopLeftTemp[1] = currentRow;
        end 
        // set columns back to 35 & 67
        assign squareTopLeftTemp[1] = colStartRow;
        // increment row
        assign squareTopLeftTemp[0] = squareTopLeftTemp[0]+blockSize;
        assign currentCol = squareTopLeftTemp[0];
        assign currentRow = squareTopLeftTemp[1];
        assign squareTopLeftTemp[0] = currentCol;
        assign squareTopLeftTemp[1] = currentRow;

    end
endgenerate

shortint row;
shortint col;

always @ (posedge in) begin

    for (row = 0 ; row <= n ; row = row + 1) begin
        for (col = 0; col <= n ; col = col + 1) begin

            $write("[%d, %d] \t",square[row][col][0],square[row][col][1]);

        end
        $display("");
    end

end

endmodule

----- OLD ----- SystemVerilog code:

parameter blockSize = 20
parameter rowStartCol = 144;
parameter rowEndCol = 784;
parameter colStartRow = 35;
parameter colEndRow = 515;
reg[9:0] squareTopLeftTemp [1:0];

reg [9:0] square[n:0][n:0][1:0]; // a n*n array of squares where each square is defined by its top left corner 
    /*
        eg, n = 5
        [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}]
        [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}]
        [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}]
        [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}]
        [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}],  [{9'b},{9'b}]

    */

    assign square[0][0][0] = 144;
    assign square[0][0][1] = 35;

    assign square[0][1][0] = 144;
    assign square[0][1][1] = 55;

    assign square[0][2][0] = 144;
    assign square[0][2][1] = 75;

    assign square[0][3][0] = 144;
    assign square[0][3][1] = 95;

    assign square[0][4][0] = 144;
    assign square[0][4][1] = 115;

    assign square[0][5][0] = 144;
    assign square[0][5][1] = 135;

    assign square[1][0][0] = 164;
    assign square[1][0][1] = 35;

    assign square[1][1][0] =  164;
    assign square[1][1][1] = 55;

    assign square[1][2][0] =  164;
    assign square[1][2][1] = 75;

    assign square[1][3][0] =  164;
    assign square[1][3][1] = 95;

    assign square[1][4][0] =  164;
    assign square[1][4][1] = 115;

    assign square[1][5][0] =  164;
    assign square[1][5][1] = 135;

    assign square[2][0][0] = 184;
    assign square[2][0][1] = 35;

    assign square[2][1][0] =  184;
    assign square[2][1][1] = 55;

    assign square[2][2][0] =  184;
    assign square[2][2][1] = 75;

    assign square[2][3][0] =  184;
    assign square[2][3][1] = 95;

    assign square[2][4][0] =  184;
    assign square[2][4][1] = 115;

    assign square[2][5][0] =  184;
    assign square[2][5][1] = 135;
    //
    assign square[4][0][0] = 204;
    assign square[4][0][1] =35;

    assign square[4][1][0] =  204;
    assign square[4][1][1] =55;

    assign square[4][2][0] =  204;
    assign square[4][2][1] =75;

    assign square[4][3][0] =  204;
    assign square[4][3][1] =95;

    assign square[4][4][0] =  204;
    assign square[4][4][1] =115;

    assign square[4][5][0] =  204;
    assign square[4][5][1] =135;
    //
    assign square[5][0][0] = 224;
    assign square[5][0][1] =35;

    assign square[5][1][0] =  224;
    assign square[5][1][1] =55;

    assign square[5][2][0] =  224;
    assign square[5][2][1] =75;

    assign square[5][3][0] =  224;
    assign square[5][3][1] =95;

    assign square[5][4][0] =  224;
    assign square[5][4][1] =115;

    assign square[5][5][0] =  224;
    assign square[5][5][1] =135;

The above code works (can synthesize).

The below code does not work (can't synthesize):

    /*    

    genvar i;
    genvar j;

    reg [9:0] currentCol; // starts at 144
    reg [9:0] currentRow; // starts at 35
    assign squareTopLeftTemp[0] = rowStartCol;
    assign squareTopLeftTemp[1] = colStartRow;
    // rowEndCol = 784
    // colEndRow = 515

    generate
        for (i = 0 ; i <= n ; i = i + 1) begin
            for (j = 0 ; j <= n; j = j + 1) begin

                // create a row of squares, columns are added, [1]
                assign square[i][j][0] = squareTopLeftTemp[0];
                assign square[i][j][1] = squareTopLeftTemp[1];

                //increment column
                assign squareTopLeftTemp[1] = squareTopLeftTemp[1]+blockSize;
                // 35 --> 67 --> 99 --> etc
                // save inputs for use on next iteration
                assign currentCol = squareTopLeftTemp[0];
                assign currentRow = squareTopLeftTemp[1];
                assign squareTopLeftTemp[0] = currentCol;
                assign squareTopLeftTemp[1] = currentRow;
            end 
            // set columns back to 35 & 67
            assign squareTopLeftTemp[1] = colStartRow; //[x,35]  (first iteration eg)  
            // increment row
            assign squareTopLeftTemp[0] = squareTopLeftTemp[0]+blockSize; // [176, y]
            assign currentCol = squareTopLeftTemp[0];
            assign currentRow = squareTopLeftTemp[1];
            assign squareTopLeftTemp[0] = currentCol;
            assign squareTopLeftTemp[1] = currentRow;

        end
    endgenerate
*/

解决方案

Verilog是一种硬件描述语言,与编程语言的工作方式不同。把硬件理解为导线、计数器和并行执行,而不是变量和顺序执行,会更有帮助。

genvar based for loops are evaluated at elaboration time, not at runtime. The synthesis tool unrolls these loops and generates independent hardware instances with constant indices, similar to manual replication.

The correct way to assign squares using genvar to replicate the squares is shown below.

localparam n = 5;
localparam blockSize = 20;

localparam rowStartCol = 144;
localparam colStartRow = 35;

wire [9:0] square[n:0][n:0][1:0];

genvar i, j;
generate
    for (i = 0 ; i <= n ; i = i + 1) begin
        for (j = 0 ; j <= n; j = j + 1) begin
            assign square[i][j][0] = rowStartCol + i*blockSize;
            assign square[i][j][1] = colStartRow + j*blockSize; 
        end
    end
endgenerate
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章