Перепишите код, используя оператор генерации (Verilog HDL)

Я пытаюсь переписать этот код, используя операторы генерации (Verilog HDL):

integer j;
always@(posedge cpu_clk) begin
        // ACCU_RST
        if(RAM[3][7]) begin
            RAM[3][7] <= 1'b0;
            for(j = 10; j <= 15; j = j + 1)
                RAM[j] <= 8'b0;
        end
        
        // CPU write
        RAM[addr + 0] <= in_valid && cmd && (addr + 0 <= 9 || addr + 0 >= 16) ? data_in[8 * 0 + 7:8 * 0] : RAM[addr + 0];
        RAM[addr + 1] <= in_valid && cmd && (addr + 1 <= 9 || addr + 1 >= 16) ? data_in[8 * 1 + 7:8 * 1] : RAM[addr + 1];
        RAM[addr + 2] <= in_valid && cmd && (addr + 2 <= 9 || addr + 2 >= 16) ? data_in[8 * 2 + 7:8 * 2] : RAM[addr + 2];
        RAM[addr + 3] <= in_valid && cmd && (addr + 3 <= 9 || addr + 3 >= 16) ? data_in[8 * 3 + 7:8 * 3] : RAM[addr + 3];

        //CPU read
        out_valid <= !cmd && in_valid;
        out_data[8 * 0 + 7:8 * 0] <= !cmd && in_valid ? RAM[addr + 0] : out_data[8 * 0 + 7:8 * 0];
        out_data[8 * 1 + 7:8 * 1] <= !cmd && in_valid ? RAM[addr + 1] : out_data[8 * 1 + 7:8 * 1];
        out_data[8 * 2 + 7:8 * 2] <= !cmd && in_valid ? RAM[addr + 2] : out_data[8 * 2 + 7:8 * 2];
        out_data[8 * 3 + 7:8 * 3] <= !cmd && in_valid ? RAM[addr + 3] : out_data[8 * 3 + 7:8 * 3];
end

Тем не менее, если я попробую это сделать, я получу следующие ошибки:

// CPU write
    for(i = 0; i <= 3; i = i + 1) begin
        if(in_valid && cmd && (addr + i <= 9 || addr + i >= 16)) 
            RAM[addr + i] <=  data_in[8 * i + 7:8 * i];
    end
    //CPU read
    out_valid <= !cmd && in_valid;
    for(i = 0; i <= 3; i = i + 1) begin
        if(in_valid && !cmd) 
            out_data[8 * i + 7:8 * i] <=  RAM[addr + i];
    end

ОШИБКА: i не является постоянным значением.

(ошибка указывает на data_in [8 * i + 7: 8 * i] и out_data [8 * i + 7: 8 * i])

Еще одна попытка, используя два блока always, один для генерации, другой для ACCU_RST, дает несколько драйверов для ОЗУ (да).

Последняя попытка:

genvar i;
always@(posedge cpu_clk) begin
    if(ACCU_RST) begin
        RAM[3][7] <= 1'b0;
        for(j = 10; j <= 15; j = j + 1)
            RAM[j] <= 8'b0;
    end
    
    // CPU write cmd
    for(i = 0; i <= 3; i = i + 1) begin :CPU_W
        if(in_valid && cmd && (addr + i <= 9 || addr + i >= 16)) 
            RAM[addr + i] <=  data_in[8 * i + 7:8 * i];
    end

    //CPU read cmd
    out_valid <= !cmd && in_valid;
    for(i = 0; i <= 3; i = i + 1) begin :CPU_R
        if(in_valid && !cmd) 
            out_data[8 * i + 7:8 * i] <=  RAM[addr + i];
    end
end

Это дает:

ОШИБКА: процедурное присвоение незарегистрированному i недопустимо, левая часть должна быть reg / integer / time / genvar

(и указывает на i = 0 и на i = i + 1).


person ZyanWu    schedule 24.08.2014    source источник


Ответы (1)


Для этого не следует использовать блок генерации. Цикл генерации for должен существовать вне блока always. И значения должны быть назначены только в одном всегда блоке, чтобы их можно было синтезировать. Рассмотрим пример ниже, RAM[2] может быть назначен, когда addr==0 в третьем цикле (i==2), когда addr==1 во втором цикле (i==1) и когда addr==2 включен в первом цикле (i==0). Три отдельных блока always, что является синтезируемой ошибкой.

genvar i;
generate
for(i=0; i<4; i++) begin
  always @(posedge clk)
    if (in_valid && cmd && (addr + i <= 9 || addr + i >= 16)) 
      RAM[addr + i] <=  data_in[8*i + 7 : 8*i];
end
endgenerate

Пропустите генерацию и используйте стандартный цикл for внутри блока always. Используйте индексированный частичный выбор (ссылки здесь и здесь):

integer i; // <-- not genvar
always @(posedge cpu_clk) begin
    /* ... your other code ... */

    // CPU write cmd
    for (i = 0; i < 4; i = i + 1) begin :CPU_W
        if (in_valid && cmd && (addr + i <= 9 || addr + i >= 16)) 
            RAM[addr + i] <=  data_in[ 8*i +: 8];
    end

    //CPU read cmd
    out_valid <= !cmd && in_valid;
    for (i = 0; i < 4; i = i + 1) begin :CPU_R
        if (in_valid && !cmd)
            out_data[ 8*i +: 8] <=  RAM[addr + i];
    end
end
person Greg    schedule 24.08.2014