Removing delay in wire to register assignment

A

Adam Preble

Guest
I posted earlier some code for a 74LS181 I am modelling. I have figured
out most of my problems -- the output is delayed by a "cycle." Now, the
module doesn't use a clock, but rather the output isn't correct until
one of the inputs has changed again. This only happens with the code
that uses the module.

Example when using addition:
A = 1, B = 1, output = X
A = 2, B = 2, output = 2
A = 8, B = 8, output = 4
A = 4, B = 4, output = 16 (0 but with carry output since it's 4 bits)

I simulated it in Silos. The output directly from the module is on-time
-- the output wire has the correct result of addition. However, the
register to which it is assigned is delayed. From there, the final
output gets delayed. So there problem happens in assigning the output
of the incorporated module to the register.

There is a lot of code in the way here -- I will try to cut it down.
Look at the arithmetic mode code, where I assign ALU_result to
adder_Sum:



code:--------------------------------------------------------------------------------
/* Module 74LS181
* A simplified version of the 74LS181 ALU chip, written in RTL
* inputs:
* inputA -- 4-bits -- first inputs
* inputB -- 4-bits -- second inputs
* cin -- 1-bit -- Carry input
* mode -- 1-bit -- logic/arithmetic toggle. Logic mode is
active-high.
* select -- 4-bits -- specifies what type of operation the unit shall
* perform:
*
* ...
*
* outputA -- 4-bits -- output of first inputs (operation) second inputs
* cout -- 1-bit -- carry output, active high
* gout -- 1-bit -- Carry generate, active low
* pout -- 1-bit -- Carry propagate, active low
* equality-- 1-bit -- true if inputs A = inputs B, active high
*/

module _74LS181_rtl (inputA, inputB, cin, mode, select,
outputA, cout, gout, pout, equality);

input [3:0] inputA, inputB, select;
input mode;
input cin;
output [3:0] outputA;
output cout, gout, pout, equality;

reg [3:0] ALU_result; // Follows the result of the ALU before & after
carry
reg [3:0] outputA; // Result of ALU with potential carry included
reg cout;
reg gout;
reg pout;
reg equality;

reg [3:0] adder_A, adder_B;
reg adder_Cin;
wire adder_Cout, adder_Gout, adder_Pout;
wire [3:0] adder_Sum;

carry_lookahead_4 adder (adder_A, adder_B, adder_Cin, adder_Sum,
adder_Cout, adder_Gout, adder_Pout);

always @ (inputA or inputB or mode or cin or select)
begin
if(mode == 1)

// Logic mode
begin
case(select)

[// You don't care]

endcase

// In logic mode, the adder is shut off. There shouldn't be
// any asserted carries, generates, or propagates.
gout = 0;
pout = 0;
cout = 0;

outputA = ALU_result;

// Test equality of A and B
equality = (inputA == inputB);

end // if-block
else

begin

// Arithmetic mode.
// Carry input applies to each arithmetic case
// Note that carry is active-low
adder_Cin <= ~cin;

case (select)

// [Lots of stuff deleted, but here's the regular
addition:]

4'b1001: begin // ALU_result = inputA + inputB;
adder_A <= inputA;
adder_B <= inputB;
end
endcase

// Assign outputs from adder.
ALU_result = adder_Sum;
cout = adder_Cout;
gout = adder_Gout;
pout = adder_Pout;

outputA = ALU_result;

// Test equality of A and B
equality = (inputA == inputB);


end // else block

end

endmodule
--------------------------------------------------------------------------------


One note: The assignments from the wire to registers doesn't change
whether I use blocking or nonblocking statements. Suggesting to us '<='
instead of '=' does nothing.
 
Adam Preble wrote:

I posted earlier some code for a 74LS181 I am modelling. I have figured
out most of my problems -- the output is delayed by a "cycle." Now, the
module doesn't use a clock, but rather the output isn't correct until
one of the inputs has changed again. This only happens with the code
that uses the module.

Example when using addition:
A = 1, B = 1, output = X
A = 2, B = 2, output = 2
A = 8, B = 8, output = 4
A = 4, B = 4, output = 16 (0 but with carry output since it's 4 bits)

I simulated it in Silos. The output directly from the module is on-time
-- the output wire has the correct result of addition. However, the
register to which it is assigned is delayed. From there, the final
output gets delayed. So there problem happens in assigning the output
of the incorporated module to the register.
(snip of verilog code containing reg statements)

It might be possible to do that way.

When I do combinatorial logic it has no reg, only wire, and
uses continuous assignment statements. I believe it is
possible to do the other way, but it seems more obvious
with continuous assignment.

The test fixture should then have the appropriate logic to
generate test signals, likely using reg and loops.

-- glen
 
Adam Preble <acp7569@rit.edu> wrote in message news:<4070EE6E.E22601A9@rit.edu>...
I posted earlier some code for a 74LS181 I am modelling. I have figured
out most of my problems -- the output is delayed by a "cycle." Now, the
module doesn't use a clock, but rather the output isn't correct until
one of the inputs has changed again. This only happens with the code
that uses the module.

Example when using addition:
A = 1, B = 1, output = X
A = 2, B = 2, output = 2
A = 8, B = 8, output = 4
A = 4, B = 4, output = 16 (0 but with carry output since it's 4 bits)

I simulated it in Silos. The output directly from the module is on-time
-- the output wire has the correct result of addition. However, the
register to which it is assigned is delayed. From there, the final
output gets delayed. So there problem happens in assigning the output
of the incorporated module to the register.

There is a lot of code in the way here -- I will try to cut it down.
Look at the arithmetic mode code, where I assign ALU_result to
adder_Sum:
Show us the code that assigns ALU_result.

-a
 
Adam Preble <acp7569@rit.edu> wrote in message news:<4070EE6E.E22601A9@rit.edu>...
I simulated it in Silos. The output directly from the module is on-time
-- the output wire has the correct result of addition. However, the
register to which it is assigned is delayed. From there, the final
output gets delayed. So there problem happens in assigning the output
of the incorporated module to the register.
That is correct. Your always block assigns the inputs to the module,
and then immediately reads the output of the module and assigns it to
the register. But at this point, the simulator has not yet evaluated
the logic in the module, so you are reading the old output value. Then
the always block loops back around to wait for another input change.

Later, the simulator evaluates the logic in the adder module and updates
the output. But the always block is not waiting on the output of the
adder, so it doesn't run again to update its own output.

Your always block is a strange construct that doesn't match any real
hardware. It isn't combinational logic, since it isn't sensitive to
every signal that it reads (i.e. the adder outputs). It is only
sensitive to the ALU inputs, but reads other inputs. So the ALU
inputs act as a sort of clock that trigger the storing of the adder
output in a register. And there is a race between the adder computing
the output (in zero delay) and the always block latching that output
(also zero delay).

This just isn't the correct way to model a combinational circuit.
 
That is correct. Your always block assigns the inputs to the module,
and then immediately reads the output of the module and assigns it to
the register. But at this point, the simulator has not yet evaluated
the logic in the module, so you are reading the old output value. Then
the always block loops back around to wait for another input change.
And it looks like you're correct too. I've been poring over this, and
ended up adding the adder's output signals to the always block. It has
been behaving correctly since then.

Your always block is a strange construct that doesn't match any real
hardware. It isn't combinational logic, since it isn't sensitive to
every signal that it reads (i.e. the adder outputs). It is only
sensitive to the ALU inputs, but reads other inputs. So the ALU

...

This just isn't the correct way to model a combinational circuit.
If my always block includes the output wires from "adder," is that
"correct?" I'm seriously about knowing that -- I plan to synthesize this
very soon and see what happens.
 

Welcome to EDABoard.com

Sponsor

Back
Top