A
Adam Preble
Guest
This is a rather basic question, but since I'm learning Verilog by what
I am scraping off the web, I just can't figure it out. I am modelling a
74LS181 in Verilog. This chip is a 4-bit ALU, with a carry look-ahead
adder for the addition. I made a model using the addition operator, but
now I want to replace that with a carry look-ahead adder I made.
For the vectors I am testing, the carry look-ahead module checked out
fine. These key vectors are:
1 + 1 = 2
2 + 2 = 4
4 + 4 = 8
8 + 8 = 16 (carries)
You should see that I have just have the same bit set in each input, and
I expect it to appear shifted left one on the output. It's a quick
test. The adder passes by itself.
My first model using the '+' operator works when I set it for addition.
Unfortunately, the model that uses the module fails for the same cases.
Assuming the adder is working, what could I be doing wrong?
It's a pretty complicated example for practicing. I use modules fine in
testbenches, but there I am not trying to do anything with the output
but log them. I might play with an easier example if I don't get any
advice.
Here's the code:
/* Module 74LS181
* A simplified version of the 74LS181 ALU chip, written in RTL
* to be easily synthesized
*
* Written by Adam Preble
* 3/22/2004
*
* The inputs are shown on datasheets as active-low, but the active-high
* functions were included in a truth table. The active-high values are
* being used for the specification.
*
* 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:
*
* (mode is high)
* 0000 /A
* 0001 /(A or B)
* 0010 /A and B
* 0011 0
* 0100 /(A and B)
* 0101 /B
* 0110 A eor B
* 0111 A and /B
* 1000 /A or B
* 1001 /(A eor B)
* 1010 B
* 1011 A and B
* 1100 1
* 1101 A or /B
* 1110 A or B
* 1111 A
*
* (mode is low)
* 0000 A
* 0001 A or B
* 0010 A or /B
* 0011 -1
* 0100 A + (A and /B)
* 0101 (A or B) + (A and /B)
* 0110 A - B - 1
* 0111 (A and /B) - 1
* 1000 A + (A and B)
* 1001 A + B
* 1010 (A or /B) + (A and B)
* 1011 (A and B) - 1
* 1100 A + A
* 1101 (A or B) + A
* 1110 (A or /B) + A
* 1111 A - 1
* when carry is enabled
*
* 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)
4'b0000: ALU_result = ~inputA;
4'b0001: ALU_result = ~(inputA | inputB);
4'b0010: ALU_result = ~inputA & inputB;
4'b0011: ALU_result = 4'b0000;
4'b0100: ALU_result = ~(inputA & inputB);
4'b0101: ALU_result = ~inputB;
4'b0110: ALU_result = inputA ^ inputB;
4'b0111: ALU_result = inputA & ~inputB;
4'b1000: ALU_result = ~inputA | inputB;
4'b1001: ALU_result = ~(inputA ^ inputB);
4'b1010: ALU_result = inputB;
4'b1011: ALU_result = inputA & inputB;
4'b1100: ALU_result = 4'b0001;
4'b1101: ALU_result = inputA | ~inputB;
4'b1110: ALU_result = inputA | inputB;
4'b1111: ALU_result = inputA;
default: ALU_result = 4'b0000;
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;
end // if-block
else
// Arithmetic mode.
// Carry input applies to each arithmetic case
// Note that carry is active-low
adder_Cin <= ~cin;
begin
case (select)
// recall cin is active-low; it must be inverted to properly
// add with the active-high representations below
4'b0000: begin //ALU_result = inputA;
adder_A = inputA;
adder_B = 4'b0000;
end
4'b0001: begin // ALU_result = inputA | inputB;
adder_A = inputA | inputB;
adder_B = 4'b0000;
end
4'b0010: begin // ALU_result = inputA | ~inputB;
adder_A = inputA | ~inputB;
adder_B = 4'b0000;
end
4'b0011: begin // ALU_result = 4'b1111; // -1 in two's
complement
adder_A = 4'b1111;
adder_B = 4'b0000;
end
4'b0100: begin // ALU_result = inputA + (inputA & ~inputB);
adder_A = inputA;
adder_B = inputA & ~inputB;
end
4'b0101: begin // ALU_result = (inputA | inputB) + (inputA &
~inputB);
adder_A = inputA | inputB;
adder_B = inputA & ~inputB;
end
4'b0110: begin // ALU_result = inputA + ~inputB; // A - B -
1 (without carry)
adder_A = inputA;
adder_B = ~inputB;
end
4'b0111: begin // ALU_result = ~inputA | inputB; // A and
~B - 1 (without carry)
adder_A = ~inputA | inputB;
adder_B = 4'b0000;
end
4'b1000: begin // ALU_result = inputA + (inputA & inputB);
adder_A = inputA;
adder_B = inputA & inputB;
end
4'b1001: begin // ALU_result = inputA + inputB;
adder_A <= inputA;
adder_B <= inputB;
end
4'b1010: begin // ALU_result = (inputA | ~inputB) + (inputA |
inputB);
adder_A = inputA | ~inputB;
adder_B = inputA | inputB;
end
4'b1011: begin // ALU_result = ~inputA | ~inputB; // inputA
& inputB - 1 (without carry)
adder_A = ~inputA | ~inputB;
adder_B = 4'b0000;
end
4'b1100: begin // ALU_result = inputA + inputA;
adder_A = inputA;
adder_B = inputA;
end
4'b1101: begin // ALU_result = (inputA | inputB) + inputA;
adder_A = inputA | inputB;
adder_B = inputA;
end
4'b1110: begin // ALU_result = (inputA | ~inputB) + inputA;
adder_A = inputA | ~inputB;
adder_B = inputA;
end
4'b1111: begin // ALU_result = ~inputA; // inputA - 1
(without carry)
adder_A = ~inputA;
adder_B = 4'b0000;
end
endcase
// Assign outputs from adder.
ALU_result = adder_Sum;
cout = adder_Cout;
gout = adder_Gout;
pout = adder_Pout;
end // else block
outputA = ALU_result;
// Test equality of A and B
equality = (inputA == inputB);
end
endmodule
I am scraping off the web, I just can't figure it out. I am modelling a
74LS181 in Verilog. This chip is a 4-bit ALU, with a carry look-ahead
adder for the addition. I made a model using the addition operator, but
now I want to replace that with a carry look-ahead adder I made.
For the vectors I am testing, the carry look-ahead module checked out
fine. These key vectors are:
1 + 1 = 2
2 + 2 = 4
4 + 4 = 8
8 + 8 = 16 (carries)
You should see that I have just have the same bit set in each input, and
I expect it to appear shifted left one on the output. It's a quick
test. The adder passes by itself.
My first model using the '+' operator works when I set it for addition.
Unfortunately, the model that uses the module fails for the same cases.
Assuming the adder is working, what could I be doing wrong?
It's a pretty complicated example for practicing. I use modules fine in
testbenches, but there I am not trying to do anything with the output
but log them. I might play with an easier example if I don't get any
advice.
Here's the code:
/* Module 74LS181
* A simplified version of the 74LS181 ALU chip, written in RTL
* to be easily synthesized
*
* Written by Adam Preble
* 3/22/2004
*
* The inputs are shown on datasheets as active-low, but the active-high
* functions were included in a truth table. The active-high values are
* being used for the specification.
*
* 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:
*
* (mode is high)
* 0000 /A
* 0001 /(A or B)
* 0010 /A and B
* 0011 0
* 0100 /(A and B)
* 0101 /B
* 0110 A eor B
* 0111 A and /B
* 1000 /A or B
* 1001 /(A eor B)
* 1010 B
* 1011 A and B
* 1100 1
* 1101 A or /B
* 1110 A or B
* 1111 A
*
* (mode is low)
* 0000 A
* 0001 A or B
* 0010 A or /B
* 0011 -1
* 0100 A + (A and /B)
* 0101 (A or B) + (A and /B)
* 0110 A - B - 1
* 0111 (A and /B) - 1
* 1000 A + (A and B)
* 1001 A + B
* 1010 (A or /B) + (A and B)
* 1011 (A and B) - 1
* 1100 A + A
* 1101 (A or B) + A
* 1110 (A or /B) + A
* 1111 A - 1
* when carry is enabled
*
* 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)
4'b0000: ALU_result = ~inputA;
4'b0001: ALU_result = ~(inputA | inputB);
4'b0010: ALU_result = ~inputA & inputB;
4'b0011: ALU_result = 4'b0000;
4'b0100: ALU_result = ~(inputA & inputB);
4'b0101: ALU_result = ~inputB;
4'b0110: ALU_result = inputA ^ inputB;
4'b0111: ALU_result = inputA & ~inputB;
4'b1000: ALU_result = ~inputA | inputB;
4'b1001: ALU_result = ~(inputA ^ inputB);
4'b1010: ALU_result = inputB;
4'b1011: ALU_result = inputA & inputB;
4'b1100: ALU_result = 4'b0001;
4'b1101: ALU_result = inputA | ~inputB;
4'b1110: ALU_result = inputA | inputB;
4'b1111: ALU_result = inputA;
default: ALU_result = 4'b0000;
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;
end // if-block
else
// Arithmetic mode.
// Carry input applies to each arithmetic case
// Note that carry is active-low
adder_Cin <= ~cin;
begin
case (select)
// recall cin is active-low; it must be inverted to properly
// add with the active-high representations below
4'b0000: begin //ALU_result = inputA;
adder_A = inputA;
adder_B = 4'b0000;
end
4'b0001: begin // ALU_result = inputA | inputB;
adder_A = inputA | inputB;
adder_B = 4'b0000;
end
4'b0010: begin // ALU_result = inputA | ~inputB;
adder_A = inputA | ~inputB;
adder_B = 4'b0000;
end
4'b0011: begin // ALU_result = 4'b1111; // -1 in two's
complement
adder_A = 4'b1111;
adder_B = 4'b0000;
end
4'b0100: begin // ALU_result = inputA + (inputA & ~inputB);
adder_A = inputA;
adder_B = inputA & ~inputB;
end
4'b0101: begin // ALU_result = (inputA | inputB) + (inputA &
~inputB);
adder_A = inputA | inputB;
adder_B = inputA & ~inputB;
end
4'b0110: begin // ALU_result = inputA + ~inputB; // A - B -
1 (without carry)
adder_A = inputA;
adder_B = ~inputB;
end
4'b0111: begin // ALU_result = ~inputA | inputB; // A and
~B - 1 (without carry)
adder_A = ~inputA | inputB;
adder_B = 4'b0000;
end
4'b1000: begin // ALU_result = inputA + (inputA & inputB);
adder_A = inputA;
adder_B = inputA & inputB;
end
4'b1001: begin // ALU_result = inputA + inputB;
adder_A <= inputA;
adder_B <= inputB;
end
4'b1010: begin // ALU_result = (inputA | ~inputB) + (inputA |
inputB);
adder_A = inputA | ~inputB;
adder_B = inputA | inputB;
end
4'b1011: begin // ALU_result = ~inputA | ~inputB; // inputA
& inputB - 1 (without carry)
adder_A = ~inputA | ~inputB;
adder_B = 4'b0000;
end
4'b1100: begin // ALU_result = inputA + inputA;
adder_A = inputA;
adder_B = inputA;
end
4'b1101: begin // ALU_result = (inputA | inputB) + inputA;
adder_A = inputA | inputB;
adder_B = inputA;
end
4'b1110: begin // ALU_result = (inputA | ~inputB) + inputA;
adder_A = inputA | ~inputB;
adder_B = inputA;
end
4'b1111: begin // ALU_result = ~inputA; // inputA - 1
(without carry)
adder_A = ~inputA;
adder_B = 4'b0000;
end
endcase
// Assign outputs from adder.
ALU_result = adder_Sum;
cout = adder_Cout;
gout = adder_Gout;
pout = adder_Pout;
end // else block
outputA = ALU_result;
// Test equality of A and B
equality = (inputA == inputB);
end
endmodule