Verilog HDL实现算术逻辑单元(ALU)
一、 ALUop与对应运算关系
需要进行描述的ALU运算器:
ALUop | 运算 | 功能描述 | SR | SV | SL | M3 | M2 | M1 | M0 | S1 | S0 |
---|---|---|---|---|---|---|---|---|---|---|---|
0000 | F=X | 传送X | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0001 | F=X+Y | 加法 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
0010 | F=X-Y | 减法 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 |
0011 | F=X &Y | 逻辑与 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
0100 | F=X or Y | 逻辑或 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
0101 | F=X ⊕Y | 逻辑异或 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
0110 | F=X/2 | 算术右移 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0111 | F=2X | 左移 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
1000 | F=!X | 逻辑非 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
1001 | F=X+1 | 加1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
1010 | F=X-1 | 减1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
1011 | F=X+Y+Cin | 带进位加法 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
1100 | F=X-Y-Cin | 带进位减法 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
二、实现方法
wire [3:0]ALUop = S[12:9];//M2
wire [3:0]M;
wire [1:0]SW;
wire Cin=S[8];
wire SR;
wire SV;
wire SL;
wire [3:0] X = S[7:4];
wire [3:0] Y = S[3:0];
logic [4:0]result;
/************* The logic of this experiment *************/
wire [3:0] A,B,F;
wire C0;
always@(ALUop[3:0])
begin
case(ALUop[3:0]) //F=X;
4'b0000:begin
SW[1:0]=2'b00;
M[3:0]=4'b0000;
SV=1'b1;
SR=1'b0;
SL=1'b0;
end
4'b0001: begin //F=X+Y
SW[1:0]=2'b00;
M[3:0]=4'b0001;
SV=1'b1;
SR=1'b0;
SL=1'b0;
end
4'b0010: begin //F=X-Y
SW[1:0]=2'b00;
SV=1'b1;
M[3:0]=4'b0110;
SR=1'b0;
SL=1'b0;
end
4'b0011:begin //F=X &Y
SV=1'b1;
SW[1:0]=2'b01;
M[3:0]=4'b0001;
SR=1'b0;
SL=1'b0;
end
4'b0100:begin // F=X or Y
SV=1'b1;
SW[1:0]=2'b10;
M[3:0]=4'b0001;
SR=1'b0;
SL=1'b0;
end
4'b0101:begin //F=X ^Y
SV=1'b1;
SW[1:0]=2'b11;
M[3:0]=4'b0001;
SL=1'b0;
SR=1'b0;
end
4'b0110:begin //F=X/2
SR=1'b1;
SV=1'b0;
SL=1'b0;
SW[1:0]=2'b00;
M[3:0]=4'b0000;
end
4'b0111:begin
SL=1'b1; //F=2X
SV=1'b0;
SR=1'b0;
SW[1:0]=2'b00;
M[3:0]=4'b0000;
end
4'b1000:begin //F=!X
SV=1'b1;
SW[1:0]=2'b11;
M[3:0]=4'b0011;
SL=1'b0;
SR=1'b0;
end
4'b1001:begin //F=X+1
SV=1'b1;
M[3:0]=4'b0100;
SL=1'b0;
SR=1'b0;
SW[1:0]=2'b00;
end
4'b1010:begin //F=X-1
SV=1'b1;
M[3:0]=4'b0011;
SL=1'b0;
SR=1'b0;
SW[1:0]=2'b00;
end
4'b1011:begin //F=X+Y+Cin
SV=1'b1;
M[3:0]=4'b1001;
SL=1'b0;
SR=1'b0;
SW[1:0]=2'b00;
end
4'b1100:begin //F=X-Y-Cin
SV=1'b1;
M[3:0]=4'b1010;
SL=1'b0;
SR=1'b0;
SW[1:0]=2'b00;
end
default:begin
SV=1'b0;
M[3:0]=4'b0000;
SL=1'b0;
SR=1'b0;
SW[1:0]=2'b00;
end
endcase
end
assign C0 = (Cin & M[3] | M[2]);
wire sign, zero, overflow, carryOut;
assign A[3]=SR & X[3] | X[3] & SV | SL &X[2] ;
assign A[2]=SR & X[3] | X[2] & SV | SL &X[1];
assign A[1]=SR & X[2] | X[1] & SV | SL &X[0] ;
assign A[0]=SR & X[1] | X[0] & SV | SL &1'b0 ;
assign B[3] =(M[0] & Y[3]) | (M[1] & !Y[3]) ;
assign B[2] =M[0] & Y[2] | M[1] & !Y[2] ;
assign B[1] =M[0] & Y[1] | M[1] & !Y[1] ;
assign B[0] =M[0] & Y[0] | M[1] & !Y[0] ;
always_comb
begin
case({SW[1:0]})
2'b00: result=A+B+C0;
2'b01: result=X & B;
2'b10: result=X |B;
2'b11: result=X ^ B;
default:result={(5){1'b0}};
endcase
end
assign carryOut=result[4];
assign F[3:0] = result[3:0];
assign sign = F[3];
assign zero = (F==0) ? 1 : 0; // ~|F;
assign overflow = (~A[3]) & ~B[3] & F[3] | (A[3]) & B[3] & ~F[3] ;
/****** Internal signal assign to output port *******/
assign L[3:0] = B[3:0];
assign L[12:9] = F;
assign L[29:26] = {M[0],M[1],M[2],M[3]};
assign L[24:23] =SW[1:0];
assign L[21:18] = {sign, zero, overflow, carryOut};
assign L[32:30]={SR,SV,SL};