tags:

views:

52

answers:

1

I have the code module below

always @(posedge Clk) begin

ForwardA = 0;
ForwardB = 0;

//EX Hazard
if (EXMEMRegWrite == 1) begin
 if (EXMEMrd != 0)
    if (EXMEMrd == IDEXrs)
        ForwardA = 2'b10;
   if (EXMEMrd == IDEXrt && IDEXTest == 0)
        ForwardB = 2'b10;
end


//MEM Hazard

if (MEMWBRegWrite == 1) begin
 if (MEMWBrd != 0) begin
    if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs)))
            if (MEMWBrd == IDEXrs)
                ForwardA = 2'b01;
    if (IDEXTest == 0) begin
        if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt)))
            if (MEMWBrd == IDEXrt)
                ForwardB = 2'b01;
    end
 end
end

end

The problem is that the output, which is ForwardA and ForwardB is not updated not on the rising clock edge rather than on the next rising clock edge... why is this?? How do I resolve so that the output is updated on the same positive rising clock edge?

Here's what I mean: alt text

ForwardA is updated with 2 on the next rising clock edge and not on the same rising clock edge

+1  A: 

I'd expect this operation. It's all to do with how your input signals, MEMWBRegWrite etc., are being driven. You have to remember that if you launch something from a clock, then other clocked blocks won't see it until the next clock edge, even though things may look coincident in your waveform viewer.

It's helpful to think of the reality of what's happening. Once you launch something from a clock edge, this can't happen right away, there'll be a small delay. You won't see these small delays in RTL sim waveforms, but they are there in the form of delta cycles.

        1             2             3
         ______        ______
clk   __|      |______|      |______|

 q   ----<======A======X=======B======X====

 n1  -----<====A+1======X======B+1=====X=====        (combinatorial/logic)
 n2  ------------------X======A+1=====X=====B+1      (sequential/clocked)

If you look at my quite brillant ascii art above, q is being set to 'B' on clock edge 2, but it takes time for this to propagate. Any @(posedge clk) blocks will see a value of 'A' for q on clock edge 2, it won't see 'B' until the next edge, 3. Which is what it looks like you're seeing.

You can generate a signal almost straight away though, if that's what you need. But to do this you'll need to use combinatorial logic (n1 above).

 wire n1;
 assign n1 = q + 1;

or

 reg n1;
 always @(*)
     n1 = q + 1;

Using sequential logic (as you are):

 reg n2;
 always @(posedge clk)
     n2 <= q + 1;

Note the '<='. This is a nonblocking assignment - its recommended to use this for assigning to things you'll want to be registers or flops in your design. Look at the Sunburst Design papers for a far better explaination.

Marty
but to do this I need to have assign inside the always block, which is not possible... because in your example above.. I want n1 to be either q+1 or q+2 depending on the result of the if statement... so how is this possible?
EquinoX
Easiest thing would be to change your clocking block above to a combo block by changing 'always @(posedge Clk)' to just 'always @(*)'. You've no nonblocking assignments, so I don't think you'll need to change anything else. Give it a whirl and let me know...But do you really need the new values for 'ForwardA' and 'ForwardB' straight away?
Marty
That's right, simply changing always (posedge clk) to always @* will give EquinoX exactly the behaviour he's looking for.
Stan