alfikpl / ao68000

The OpenCores ao68000 IP Core is a Motorola MC68000 binary compatible processor.
Other
77 stars 16 forks source link

Blocking vs. Non-Blocking Assignments #2

Open aboxer opened 12 years ago

aboxer commented 12 years ago

ao68000.v line 2841 shows result assigned with a non-blocking assignment.

a068000.v line 2852 shows result assigned with a blocking assignment.

I don't know what that the Altera synthesizer does with mixed assignment like this but Xilinx XST will fail and report an error.

This occurs in many places and I am sure that if this design ran on an Altera DE2-70 then the synthesizer resolved it in a consistent manner.

I could make them consistent in the source but I need to know what behavior is intended in the design.

thanks, Aaron Boxer

alfikpl commented 12 years ago

The reason there are blocking assignments is to make it possible to use the result of the assigment in the same clock cycle as the assignment itself.

Example:

[...] // OR,OR to mem,OR to Dn if(decoder_alu_reg[0]) result[31:0] = operand1[31:0] | operand2[31:0]; // AND,AND to mem,AND to Dn else if(decoder_alu_reg[1]) result[31:0] = operand1[31:0] & operand2[31:0]; [...]

// Z sr[2] <= `Z; // <-- the Z macro uses the result[31:0] value assigned above and checks is the result zero


I believe a more appropriate way to express the same behavior would be to use a wire with a continuous assignment and use only non-blocking assignments to registers.

I am downloading Xilinx ISE WebPACK right now to check on the errors. I hope to comment on this issue later this week.

There is someone else also working on porting the ao68000 to Xilinx, so I believe that in the near future a Xilinx-compatible version of ao68000 will appear on GitHub.

Best regards, Aleksander Osman.

aboxer commented 12 years ago

Yes, but you have both blocking and non-blocking assignments for the same register in the same clock block.

ao68000.v line 2841 result <= { {16{operand1[15]}}, operand1[15:0] }; line 2852 if(decoder_alu_reg[0]) result[31:0] = operand1[31:0] | operand2[31:0];

Most synthesizers don't know what to do with this. They can synthesize result so it is available in the same clock cycle or the next one but not both. What does the Altera synthesizer do?

thanks, Aaron Boxer


From: Aleksander Osman reply@reply.github.com To: aboxer aboxer51@yahoo.com Sent: Tuesday, March 6, 2012 2:34 PM Subject: Re: [ao68000] Blocking vs. Non-Blocking Assignments (#2)

The reason there are blocking assignments is to make it possible to use the result of the assigment in the same clock cycle as the assignment itself.

Example: // OR,OR to mem,OR to Dn if(decoder_alu_reg[0]) result[31:0] = operand1[31:0] | operand2[31:0]; // AND,AND to mem,AND to Dn else if(decoder_alu_reg[1]) result[31:0] = operand1[31:0] & operand2[31:0];

I believe a wire


Reply to this email directly or view it on GitHub: https://github.com/alfikpl/ao68000/issues/2#issuecomment-4351329

alfikpl commented 12 years ago

I am not sure if I understand this issue. Let's discuss a concrete example:

module blocking(
    input             clk,
    input             rst_n,

    input             sel1,
    input             sel2,
    input             sel3,
    input [1:0]       operand1,
    input [1:0]       operand2,

    output reg [1:0]  result,
    output reg        zero
);
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        result  <= 2'd0;
        zero    <= 1'b0;
    end
    else begin
        case(sel1)
            1'b0: begin
                result <= { {1{operand1[1]}}, operand1[0] };
            end
            1'b1: begin
                if(sel2)        result[1:0] = operand1[1:0] | operand2[1:0];
                else if(sel3)   result[1:0] = operand1[1:0] & operand2[1:0];

                zero <= (result == 2'd0);
            end
        endcase
    end
end
endmodule

This module compiles under Altera Quartus II and the result is presented on the image bellow:

Altera Quartus II RTL view

The same module does not compile under Xilinx ISE with an error: Line 11: Mix of blocking and non-blocking assignments to variable is not a recommended coding practice.

If this is not the error you are getting, please write a small example module so that I can understand what is the problem.

Thanks, Aleksander Osman.

rkrajnc commented 12 years ago

alfikpl: I'm sorry for chiming in, I'd just like to clarify something.

In an always statement with posedge / negedge keyword, you are always describing a flip-flop (this is always_ff in SystemVerilog), since this is the element that is edge sensitive. All other always statements are either combinatorial logic (always_comb in SV) or a latch.

Always use non-blocking assignments in always_ff blocks. Always use blocking assignments in always_comb blocks. It is possible to do otherwise, but it is bad practice and not recommended. The described way is the only one that makes sense, well for me anyway.

Also, all flip-flops will have their value updated in the next clock cycle. All combinatorial logic will have its value updated "immediately".

Regards,

Rok

aboxer commented 12 years ago

First, I get the same xilinx error you do.

Second, your example looks like it sets zero to the blocking (combinatorial) result. Is that the desired behavior? If you put zero <= (result == 2'd0); ahead of the if/else in your example I suspect it would use the register output.

Third, since the register result is declared as a port in your example, the synthesizer will only use the registered version of result outside the module. But ao68000.v is different. Which version of result is used on line 2863 and everyplace else the define on line 2762 is used?

Finally, since the use of blocking and non-blocking result are interspersed with the use of the defines on lines 2760, 2762 and the synthesizer will pick which version of result to use depending on line order in the source code, I think the person trying to make a xilinx version of this will have a very hard time getting it right.

alfikpl commented 12 years ago

Thank you for your helpful and precise comments. I am currently working on removing blocking assignments in ao68000. I should be ready this weekend.

Regards, Aleksander Osman.

alfikpl commented 12 years ago

I commited a version without blocking assignments in alu and register modules. I have only tested the changes by running the new ao68000 in the aoOCS project -- the Amiga boots and runs software the same as before.

I plan to do full tests at some later date.