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