【计算机组成原理】实验2
使用Verilog语言实现一个简单ALU,测试平台:Vivado
①代码:
alu.v:
`timescale 1ns / 1ps
module alu(
input [11:0] alu_control, // ALU控制信号
input [31:0] alu_src1, // ALU操作数1,为补码
input [31:0] alu_src2, // ALU操作数2,为补码
output [31:0] alu_result // ALU结果
);
wire alu_add; //加法操作
wire alu_sub; //减法操作
wire alu_slt; //有符号比较,小于置位,复用加法器做减法
wire alu_sltu; //无符号比较,小于置位,复用加法器做减法
wire alu_and; //按位与
wire alu_nor; //按位或非
wire alu_or; //按位或
wire alu_xor; //按位异或
wire alu_sll; //逻辑左移
wire alu_srl; //逻辑右移
wire alu_sra; //算术右移
wire alu_lui; //高位加载
assign alu_add = alu_control[11];
assign alu_sub = alu_control[10];
assign alu_slt = alu_control[ 9];
assign alu_sltu = alu_control[ 8];
assign alu_and = alu_control[ 7];
assign alu_nor = alu_control[ 6];
assign alu_or = alu_control[ 5];
assign alu_xor = alu_control[ 4];
assign alu_sll = alu_control[ 3];
assign alu_srl = alu_control[ 2];
assign alu_sra = alu_control[ 1];
assign alu_lui = alu_control[ 0];
wire [31:0] add_sub_result;
wire [31:0] slt_result;
wire [31:0] sltu_result;
wire [31:0] and_result;
wire [31:0] nor_result;
wire [31:0] or_result;
wire [31:0] xor_result;
wire [31:0] sll_result;
wire [31:0] srl_result;
wire [31:0] sra_result;
wire [31:0] lui_result;
wire signed [31:0] temp_src1;
assign temp_src1 = alu_src1;
assign and_result = alu_src1 & alu_src2;
assign or_result = alu_src1 | alu_src2;
assign nor_result = ~or_result;
assign xor_result = alu_src1 ^ alu_src2;
assign lui_result = {alu_src2[15:0], 16'd0};
wire [31:0] adder_operand1;
wire [31:0] adder_operand2;
wire [31:0] adder_result;
wire adder_cin;
wire adder_cout;
assign adder_operand1 = alu_src1;
assign adder_operand2 = alu_add ? alu_src2 : ~alu_src2; // 1+ , 0-
assign adder_cin = ~alu_add;
adder adder_module(
.operand1(adder_operand1),
.operand2(adder_operand2),
.cin(adder_cin),
.result(adder_result),
.cout(adder_cout)
);
assign add_sub_result = adder_result;
assign slt_result = adder_result[31] ? 1'b1 : 1'b0;
assign sltu_result = adder_cout ? 1'b0 : 1'b1;
wire [4:0] shf;
assign shf = alu_src1[4:0];
wire [1:0] shf_1_0;
wire [1:0] shf_3_2;
assign shf_1_0 = shf[1:0];
assign shf_3_2 = shf[3:2];
wire [31:0] sll_step1;
wire [31:0] sll_step2;
assign sll_step1 = {32{shf_1_0 == 2'b00}} & alu_src2
| {32{shf_1_0 == 2'b01}} & {alu_src2[30:0], 1'd0}
| {32{shf_1_0 == 2'b10}} & {alu_src2[29:0], 2'd0}
| {32{shf_1_0 == 2'b11}} & {alu_src2[28:0], 3'd0};
assign sll_step2 = {32{shf_3_2 == 2'b00}} & sll_step1
| {32{shf_3_2 == 2'b01}} & {sll_step1[27:0], 4'd0}
| {32{shf_3_2 == 2'b10}} & {sll_step1[23:0], 8'd0}
| {32{shf_3_2 == 2'b11}} & {sll_step1[19:0], 12'd0};
assign sll_result = shf[4] ? {sll_step2[15:0], 16'd0} : sll_step2;
assign srl_result = alu_src1 >> alu_src2;
assign sra_result = temp_src1 >>> alu_src2;
assign alu_result = (alu_add|alu_sub) ? add_sub_result[31:0] :
alu_slt ? slt_result :
alu_sltu ? sltu_result :
alu_and ? and_result :
alu_nor ? nor_result :
alu_or ? or_result :
alu_xor ? xor_result :
alu_sll ? sll_result :
alu_srl ? srl_result :
alu_sra ? sra_result :
alu_lui ? lui_result :
32'd0;
endmodule
Adder_module:
adder.v:
`timescale 1ns / 1ps
module adder(
input [31:0] operand1,
input [31:0] operand2,
input cin,
output [31:0] result,
output cout
);
assign {cout,result} = operand1 + operand2 + cin;
endmodule
TestBench.v:
`timescale 1ns / 1ps
module tb;
reg clk;
reg [11:0] alu_control;
reg [31:0] alu_src1;
reg [31:0] alu_src2;
wire [31:0] alu_result;
alu al(
.alu_control(alu_control),
.alu_src1(alu_src1),
.alu_src2(alu_src2),
.alu_result(alu_result)
);
initial begin
clk = 0;
alu_control = 0;
#10;
alu_src1 = 32'H00001111;
alu_src2 = 32'H00000008;
alu_control = 12'b0000_0000_0001;
#40;
alu_src1 = 32'HF0001234;
alu_src2 = 32'H00000008;
alu_control = 12'b0000_0000_0010;
#40;
alu_src1 = 32'HF0001234;
alu_src2 = 32'H00000008;
alu_control = 12'b0000_0000_0100;
#40;
alu_src1 = 32'H00012345;
alu_src2 = 32'H00000008;
alu_control = 12'b0000_0000_1000;
#40;
alu_src1 = 32'H00001111;
alu_src2 = 32'H00000101;
alu_control = 12'b0000_0001_0000;
#40;
alu_control = 12'b0000_0010_0000;
#40;
alu_control = 12'b0000_0100_0000;
#40;
alu_control = 12'b0000_1000_0000;
#40;
alu_control = 12'b0001_0000_0000;
#40;
alu_control = 12'b0010_0000_0000;
#40;
alu_control = 12'b0100_0000_0000;
#40;
alu_control = 12'b1000_0000_0000;
#40; //end
alu_control = 0;
alu_src1 = 32'H00000000;
alu_src2 = 32'H00000000;
end
always #5 clk = ~clk;
endmodule
②仿真图像及其分析:
alu_control=001时进行alu_src2的高位加载,
002时进行alu_src1的算术右移,
004时进行alu_src1的逻辑右移,
008时进行alu_src1的逻辑左移,
010时进行按位异或,020时进行按位或,040时进行按位或非,080时进行按位与,
100时进行无符号比较,200时进行有符号比较
400时进行减法操作,800时进行加法操作。