1.ALU(算術邏輯單元)的16種運算的編碼
ALU的訊號說明如下:
`define A_ADD_B 5'b00001 // A 加 B
`define A_ADD_B_ADD_CIN 5'b00010 // A 加 B 加 Cin
`define A_SUB_B 5'b00011 // A 減 B 減
`define A_SUB_B_SUB_CIN 5'b00100 // A 減 B 減 Cin
`define B_SUB_A 5'b00101 // B 減 A
`define B_SUB_A_SUB_CIN 5'b00110 // B 減 A 減 Cin
`define VALUE_A 5'b00111 // F = A
`define VALUE_B 5'b01000 // F = B
`define NOT_A 5'b01001 // F = /A
`define NOT_B 5'b01010 // F = /B
`define A_OR_B 5'b01011 // F = A + B
`define A_AND_B 5'b01100 // F = AB
`define A_XNOR_B 5'b01101 // 同或
`define A_XOR_B 5'b01110 // 互斥或
`define A_NAND_B 5'b01111 // F = /(AB)
`define ZERO_FLAG 5'b10000 // F = 0
module alu (
input [31:0] A ,
input [31:0] B ,
input Cin ,
input [4 :0] Card,
output [31:0] F ,
output Cout,
output Zero
);
wire [31:0] a_add_b_result;
wire [31:0] a_add_b_add_cin_result;
wire [31:0] a_sub_b_result;
wire [31:0] a_sub_b_sub_cin_result;
wire [31:0] b_sub_a_result;
wire [31:0] b_sub_a_sub_cin_result;
wire [31:0] value_a_result;
wire [31:0] value_b_result;
wire [31:0] not_a_result;
wire [31:0] not_b_result;
wire [31:0] a_or_b_result;
wire [31:0] a_and_b_result;
wire [31:0] a_xnor_b_result;
wire [31:0] a_xor_b_result;
wire [31:0] a_nand_b_result;
wire [31:0] zero_flag_result;
// 6 個進位
wire cout_1;
wire cout_2;
wire cout_3;
wire cout_4;
wire cout_5;
wire cout_6;
// 16 種運算
assign {cout1, a_add_b_result} = A + B;
assign {cout2, a_add_b_add_cin_result} = A + B + Cin;
assign {cout3, a_sub_b_result} = A - B;
assign {cout4, a_sub_b_sub_cin_result} = A - B - Cin;
assign {cout5, b_sub_a_result} = B - A;
assign {cout6, b_sub_a_sub_cin_result} = B - A - Cin;
assign value_a_result = A;
assign value_b_result = B;
assign not_a_result = ~A;
assign not_b_result = ~B;
assign a_or_b_result = A | B;
assign a_and_b_result = A & B;
assign a_xnor_b_result = ~(A ^ B);
assign a_xor_b_result = A ^ B;
assign a_nand_b_result = ~(A & B);
assign zero_flag_result = 0;
// 運算結果 依據操作碼Card選擇
assign F = ({32{Card == `A_ADD_B}} & a_add_b_result) |
({32{Card == `A_ADD_B_ADD_CIN}} & a_add_b_add_cin_result) |
({32{Card == `A_SUB_B}} & a_sub_b_result) |
({32{Card == `A_SUB_B_SUB_CIN}} & a_sub_b_sub_cin_result) |
({32{Card == `B_SUB_A}} & b_sub_a_result) |
({32{Card == `B_SUB_A_SUB_CIN}} & b_sub_a_sub_cin_result) |
({32{Card == `VALUE_A}} & value_a_result) |
({32{Card == `VALUE_B}} & value_b_result) |
({32{Card == `NOT_A}} & not_a_result) |
({32{Card == `NOT_B}} & not_b_result) |
({32{Card == `A_OR_B}} & a_or_b_result) |
({32{Card == `A_AND_B}} & a_and_b_result) |
({32{Card == `A_XNOR_B}} & a_xnor_b_result) |
({32{Card == `A_XOR_B}} & a_xor_b_result) |
({32{Card == `A_NAND_B}} & a_nand_b_result) |
({32{Card == `ZERO_FLAG}} & zero_flag_result) |
0;
// 進位標誌
assign Cout = ({Card == `A_ADD_B} & cout1) |
({Card == `A_ADD_B_ADD_CIN} & cout2) |
({Card == `A_SUB_B} & cout3) |
({Card == `A_SUB_B_SUB_CIN} & cout4) |
({Card == `B_SUB_A} & cout5) |
({Card == `B_SUB_A_SUB_CIN} & cout6) |
0;
// 0標誌,F為0時為1
assign Zero = (F == 0) | 0;
endmodule
`timescale 1ns / 1ps
module sim();
reg [31:0] A;
reg [31:0] B;
reg Cin;
reg [4:0] Card;
wire Cout;
wire [31:0] F;
wire Zero;
initial begin
Card = 5'b00000;
A = 32'h0000_0000;
B = 32'h0000_0000;
Cin = 1'b0;
#10 // F = A 加 B
Card = 5'b00001;
A = 32'hffff_ffff;
B = 32'h0000_0001;
Cin = 1'b1;
#10 // F = A 加 B 加 Cin
Card = 5'b00010;
A = 32'hffff_ffff;
B = 32'h0000_0001;
Cin = 1'b1;
#10 // F = A 減 B
Card = 5'b00011;
A = 32'h0000_0001;
B = 32'h0000_0002;
Cin = 1'b1;
#10 // F = A 減 B 減 Cin
Card = 5'b00100;
A = 32'h0000_0001;
B = 32'h0000_0002;
Cin = 1'b1;
#10 // F = B 減 A
Card = 5'b00101;
A = 32'h0000_0002;
B = 32'h0000_0001;
Cin = 1'b1;
#10 // F = B 減 A 減 Cin
Card = 5'b00110;
A = 32'h0000_0002;
B = 32'h0000_0001;
Cin = 1'b1;
#10 // F = A
Card = 5'b00111;
A = 32'h0000_0002;
B = 32'h0000_0001;
#10 // F = B
Card = 5'b01000;
A = 32'h0000_0002;
B = 32'h0000_0001;
#10 // F = /A
Card = 5'b01001;
A = 32'h0000_0001;
#10 // F = /B
Card = 5'b01010;
B = 32'h0000_0002;
#10 // F = A + B
Card = 5'b01011;
A = 32'h0000_0001;
B = 32'hffff_fff0;
#10 // F = AB
Card = 5'b01100;
A = 32'h0000_0001;
B = 32'hffff_ffff;
#10 // F = A XNOR B
Card = 5'b01101;
A = 32'h0000_f0f0;
B = 32'h0f0f_0000;
#10 // F = A XOR B
Card = 5'b01110;
A = 32'h0000_f0f0;
B = 32'h0f0f_0000;
#10 // F = /(AB)
Card = 5'b01111;
A = 32'h0808_f0f0;
B = 32'h0f0f_8888;
#10 // F = 0
Card = 5'b10000;
#10 Card = 5'b10010;
#10 Card = 5'b10010;
#10 Card = 5'b10011;
#10 Card = 5'b10100;
#10 Card = 5'b10101;
#10 Card = 5'b10110;
#10 Card = 5'b10111;
#10 Card = 5'b11000;
#10 Card = 5'b11001;
#10 Card = 5'b11010;
#10 Card = 5'b11011;
#10 Card = 5'b11100;
#10 Card = 5'b11101;
#10 Card = 5'b11110;
#10 Card = 5'b11111;
end
alu u0 (
.A(A),
.B(B),
.Cin(Cin),
.Card(Card),
.F(F),
.Cout(Cout),
.Zero(Zero)
);
endmodule
運算功能 | A(H) | B(H) | Cin | 操作碼 (五位) | F(H) | Zero |
---|---|---|---|---|---|---|
F=A加B | FFFF_FFFF | 0000_0001 | 1 | 00001 | 0000_0000 | 1 |
F=A加B加Cin | FFFF_FFFF | 0000_0001 | 1 | 00010 | 0000_0001 | 0 |
F=A減B | 0000_0001 | 0000_0002 | 1 | 00011 | FFFF_FFFF | 0 |
F=A減B減Cin | 0000_0001 | 0000_0002 | 1 | 00100 | FFFF_FFFE | 0 |
F=B減A | 0000_0002 | 0000_0001 | 1 | 00101 | FFFF_FFFF | 0 |
F= B減A減Cin | 0000_0002 | 0000_0001 | 1 | 00110 | FFFF_FFFE | 0 |
F=A | 0000_0002 | 0000_0001 | 1 | 00111 | 0000_0002 | 0 |
F=B | 0000_0002 | 0000_0001 | 1 | 01000 | 0000_0001 | 0 |
F=/A | 0000_0001 | 0000_0001 | 1 | 01001 | FFFF_FFFE | 0 |
F=/B | 0000_0001 | 0000_0002 | 1 | 01010 | FFFF_FFFD | 0 |
F=A+B | 0000_0001 | FFFF_FFF0 | 1 | 01011 | FFFF_FFF1 | 0 |
F=AB | 0000_0001 | FFFF_FFFF | 1 | 01100 | 0000_0001 | 0 |
F=A⊙B | 0000_F0F0 | 0F0F_0000 | 1 | 01101 | F0F0_0F0F _ _ | 0 |
F=A⊕B | 0000_F0F0 | 0F0F_0000 | 1 | 01110 | 0F0F_F0F0 | 0 |
F=/(AB) | 0808_F0F0 | 0F0F_8888 | 1 | 01111 | F7F7_7F7F | 0 |
F=0 | 0808_F0F0 | 0F0F_8888 | 1 | 10000 | 0000_0000 | 1 |
對比實驗結果與正確運算結果,實驗結果符合預期。在前6個算術運算操作中,進位訊號Cout表現正確。
比如在第2個「F=A加B加Cin」操作中,選取的例子為「A = ffff_ffffH, B = 0000_0001H, Cin = 1」,結果應為進1位,和為0000_0001H,結果正確。
邏輯運算中,測試用例較為複雜,如操作15與非運算,「A = 0808_f0f0H, B = 0f0f_8888H, F = f7f7_7f7fH」,結果正確。當運算操作碼無效時,結果輸出0。
本次實驗利用Vivado開發環境和Verilog硬體描述語言實現了一個簡單的算術邏輯單元。通過本次實驗,我們鞏固了所學的數位邏輯知識,鍛鍊了硬體思維,提高了自身動手能力。
本文來自部落格園,作者:江水為竭,轉載請註明原文連結:https://www.cnblogs.com/Az1r/p/17672335.html