0

I'm trying to rewrite this code using generate statements (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

Yet I recieve the following errors if I try this:

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

ERROR: i is not a constant value.

(error points to data_in[8 * i + 7:8 * i] and out_data[8 * i + 7:8 * i])

Another try, using two always blocks, one for generate, one for ACCU_RST yields multiple drivers for RAM (duh).

Last try:

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

That yields:

ERROR: Procedural assignment to a non-register i is not permitted, left-hand side should be reg/integer/time/genvar

(and points to i = 0 and to i = i + 1).

1 Answer 1

1

For this you shouldn't use a generate block. The generate for loop must exist outside of an always block. And a values must only be assigned in one always block to be synthesizable. Take the below example, RAM[2] can be assigned when addr==0 on the third loop (i==2), when addr==1 on the second loop (i==1), and when addr==2 on on the first loop (i==0). Three separate always blocks which is a synthesizable error.

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

Skip the generate and use a standard for loop inside the always block. Use indexed part-select (references here and here):

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.