verilog实现适应RISC-V的ALU

本文基于《计算机组成与设计硬件/软件接口  RISC-V版 原书第5版》 (戴维 A.帕特森_ 约翰 L.亨尼斯)中关于ALU设计部分的verilog实现

一、硬件结构

采用书中适应于RISC-V架构的64位ALU设计,主要完成与、或、或非等逻辑运算、加法减法等基本算术运算以及小于等于置位slt指令和条件跳转指令bne指令的实现。

1.1位ALU结构

1)非最高有效位ALU

verilog实现适应RISC-V的ALU_第1张图片

//------------------------------适应RISC-V的1位ALU(非最高位ALU)---------------------------------
module ALU_1bit(
    input a,
    input b,
    input less,
    input Ainvert,
    input Binvert,
    input CarryIn,
    input [1:0] Operation,
    output reg Result,
    output CarryOut
);

wire a_n,b_n;
assign a_n=(Ainvert==0)?a:~a;
assign b_n=(Binvert==0)?b:~b;
assign CarryOut=(a_n&b_n)|(a_n&CarryIn)|(b_n&CarryIn);

always@(*)
    begin
        case (Operation)
            2'b00:Result=a_n & b_n;
            2'b01:Result=a_n | b_n;
            2'b10:Result=a_n^b_n^CarryIn;
            2'b11:Result=less;
        endcase
    end
endmodule
//-----------------------------------------------------------------------------------------------
2)最高有效位ALU

verilog实现适应RISC-V的ALU_第2张图片

其中溢出检测单元的设计如下:

溢出检测在进行加法和减法运算时被使用,一共只有4种情况会发生溢出:
verilog实现适应RISC-V的ALU_第3张图片
Overflow=a^Set&((~a^b)^Binvert)

//--------------------------------适应RISC-V的1位ALU(最高位ALU)---------------------------------
module ALU_Hbit(
    input a,
    input b,
    input less,
    input Ainvert,
    input Binvert,
    input CarryIn,
    input [1:0] Operation,
    output reg Result,
    output Set,
    output Overflow
);

wire a_n,b_n;
assign a_n=(Ainvert==0)?a:~a;
assign b_n=(Binvert==0)?b:~b;
assign Set=a_n^b_n^CarryIn;

always@(*)
    begin
        case (Operation)
            2'b00:Result=a_n & b_n;
            2'b01:Result=a_n | b_n;
            2'b10:Result=Set;
            2'b11:Result=less;
            default:Result=0;
        endcase
    end

//Overflow 溢出检测逻辑
assign Overflow=a^Set&((~a^b)^Binvert);

endmodule
//-----------------------------------------------------------------------------------------------

2.64位串行ALU结构

verilog实现适应RISC-V的ALU_第4张图片

书上给出的上图结构在减法溢出时无法实现slt小于比较置位,但仿真结果发现:当减法溢出时,ALU63的Set位取反即为对应结果,故只需要在ALU63的Set位和Overflow位异或之后传递到ALU0的less位输入即可实现。

//----------------------------------------64位串行ALU--------------------------------------------
module ALU_RISC_V(
	input [63:0]    ALU_DA,
    input [63:0]    ALU_DB,
    input [3:0]     ALU_Operation,
    output          Zero,
    output          Overflow,
    output [63:0]   Result
        );
    genvar i;
    wire CarryOut[62:0],less0,Set;
    assign less0=Overflow^Set;
    ALU_1bit alu0(
        .a(ALU_DA[0]),
        .b(ALU_DB[0]),
        .less(less0),
        .Ainvert(ALU_Operation[3]),
        .Binvert(ALU_Operation[2]),
        .CarryIn(ALU_Operation[2]),
        .Operation(ALU_Operation[1:0]),
        .Result(Result[0]),
        .CarryOut(CarryOut[0])
    );
    generate
        for(i=1;i<63;i=i+1)
        begin:ALU_62bit
            ALU_1bit alu(
                .a(ALU_DA[i]),
                .b(ALU_DB[i]),
                .less(1'b0),
                .Ainvert(ALU_Operation[3]),
                .Binvert(ALU_Operation[2]),
                .CarryIn(CarryOut[i-1]),
                .Operation(ALU_Operation[1:0]),
                .Result(Result[i]),
                .CarryOut(CarryOut[i])
            );
        end
    endgenerate
    ALU_Hbit alu63(
        .a(ALU_DA[63]),
        .b(ALU_DB[63]),
        .less(1'b0),
        .Ainvert(ALU_Operation[3]),
        .Binvert(ALU_Operation[2]),
        .CarryIn(CarryOut[62]),
        .Operation(ALU_Operation[1:0]),
        .Result(Result[63]),
        .Set(Set),
        .Overflow(Overflow)
    );
    assign Zero=~|Result;
endmodule
//-----------------------------------------------------------------------------------------------

3.ALU_Operation控制信号

ALU_Operation={Ainvert,Bnegate,Operation[1:0]}
verilog实现适应RISC-V的ALU_第5张图片

4.最终代码实现

`timescale 1ns / 1ps
//
// Company: NJUEE
// Engineer: xixi
// 
// Create Date: 2023/09/08 20:22:22
// Design Name: 
// Module Name: ALU_RISC_V
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

//ALU_Operation :{Ainvert,Bnegate,Operation[1:0]}
//0000 与    
//0001 或    
//0010 加     
//0110 减     
//0111 小于比较置位      
//1100 或非


//----------------------------------------64位串行ALU--------------------------------------------
module ALU_RISC_V(
	input [63:0]    ALU_DA,
    input [63:0]    ALU_DB,
    input [3:0]     ALU_Operation,
    output          Zero,
    output          Overflow,
    output [63:0]   Result
        );
    genvar i;
    wire CarryOut[62:0],less0,Set;
    assign less0=Overflow^Set;
    ALU_1bit alu0(
        .a(ALU_DA[0]),
        .b(ALU_DB[0]),
        .less(less0),
        .Ainvert(ALU_Operation[3]),
        .Binvert(ALU_Operation[2]),
        .CarryIn(ALU_Operation[2]),
        .Operation(ALU_Operation[1:0]),
        .Result(Result[0]),
        .CarryOut(CarryOut[0])
    );
    generate
        for(i=1;i<63;i=i+1)
        begin:ALU_62bit
            ALU_1bit alu(
                .a(ALU_DA[i]),
                .b(ALU_DB[i]),
                .less(1'b0),
                .Ainvert(ALU_Operation[3]),
                .Binvert(ALU_Operation[2]),
                .CarryIn(CarryOut[i-1]),
                .Operation(ALU_Operation[1:0]),
                .Result(Result[i]),
                .CarryOut(CarryOut[i])
            );
        end
    endgenerate
    ALU_Hbit alu63(
        .a(ALU_DA[63]),
        .b(ALU_DB[63]),
        .less(1'b0),
        .Ainvert(ALU_Operation[3]),
        .Binvert(ALU_Operation[2]),
        .CarryIn(CarryOut[62]),
        .Operation(ALU_Operation[1:0]),
        .Result(Result[63]),
        .Set(Set),
        .Overflow(Overflow)
    );
    assign Zero=~|Result;
endmodule
//-----------------------------------------------------------------------------------------------



//------------------------------适应RISC-V的1位ALU(非最高位ALU)---------------------------------
module ALU_1bit(
    input a,
    input b,
    input less,
    input Ainvert,
    input Binvert,
    input CarryIn,
    input [1:0] Operation,
    output reg Result,
    output CarryOut
);

wire a_n,b_n;
assign a_n=(Ainvert==0)?a:~a;
assign b_n=(Binvert==0)?b:~b;
assign CarryOut=(a_n&b_n)|(a_n&CarryIn)|(b_n&CarryIn);

always@(*)
    begin
        case (Operation)
            2'b00:Result=a_n & b_n;
            2'b01:Result=a_n | b_n;
            2'b10:Result=a_n^b_n^CarryIn;
            2'b11:Result=less;
        endcase
    end
endmodule
//-----------------------------------------------------------------------------------------------




//--------------------------------适应RISC-V的1位ALU(最高位ALU)---------------------------------
module ALU_Hbit(
    input a,
    input b,
    input less,
    input Ainvert,
    input Binvert,
    input CarryIn,
    input [1:0] Operation,
    output reg Result,
    output Set,
    output Overflow
);

wire a_n,b_n;
assign a_n=(Ainvert==0)?a:~a;
assign b_n=(Binvert==0)?b:~b;
assign Set=a_n^b_n^CarryIn;

always@(*)
    begin
        case (Operation)
            2'b00:Result=a_n & b_n;
            2'b01:Result=a_n | b_n;
            2'b10:Result=Set;
            2'b11:Result=less;
            default:Result=0;
        endcase
    end

//Overflow 溢出检测逻辑
assign Overflow=a^Set&((~a^b)^Binvert);

endmodule
//-----------------------------------------------------------------------------------------------

二、仿真测试

仿真测试代码如下:进行具体仿真时只需替换initial块中对应内容

`timescale 1ns / 1ps
//
// Company: NJUEE
// Engineer: xixi
// 
// Create Date: 2023/09/08 20:43:54
// Design Name: 
// Module Name: tb_ALU_RISC_V
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
//ALU_Operation :{Ainvert,Bnegate,Operation[1:0]}
//0000 与    
//0001 或    
//0010 加     
//0110 减     
//0111 小于比较置位      
//1100 或非

module tb_ALU_RISC_V(
    );
	reg[63:0]    ALU_DA;
    reg[63:0]    ALU_DB;
    reg[3:0]     ALU_Operation;
    wire          Zero;
    wire          Overflow;
    wire [63:0]   Result;
    
initial
begin
    ALU_DA=64'h8000000000000009;
    ALU_DB=64'h7fffffffffffffff;
    ALU_Operation=4'b0111;
end

ALU_RISC_V alu(
    .ALU_DA(ALU_DA),
    .ALU_DB(ALU_DB),
    .ALU_Operation(ALU_Operation),
    .Zero(Zero),
    .Overflow(Overflow),
    .Result(Result)
);
endmodule

1.算术运算

无符号数和有符号数的算术运算验证大致相同,区别仅有溢出标志位的判断,以下均只验证有符号数

1)加法         ALU_Operation=4'b0010
a.正+正

000586ab00459259H+000584abe69f24b4H
=1555443885642329+1553248727016628
=3108692612658957
=000b0b56e6e4e70dH

initial
begin
    ALU_DA=64'h000586ab00459259;
    ALU_DB=64'h000584abe69f24b4;
    ALU_Operation=4'b0010;
end
verilog实现适应RISC-V的ALU_第6张图片
b.正+负

000586ab00459259H+fffa7b541960db4cH
=1555443885642329+(-1553248727016628)
=2195158625701
=0001ff19a66da5H

initial
begin
    ALU_DA=64'h000586ab00459259;
    ALU_DB=64'hfffa7b541960db4c;
    ALU_Operation=4'b0010;
end
verilog实现适应RISC-V的ALU_第7张图片c.负+负

fffa7954ffba6da7H+fffa7b541960db4cH
=-1555443885642329+(-1553248727016628)
=-3108692612658957
=000b0b56e6e4e70dH

initial
begin
    ALU_DA=64'hfffa7954ffba6da7;
    ALU_DB=64'hfffa7b541960db4c;
    ALU_Operation=4'b0010;
end

verilog实现适应RISC-V的ALU_第8张图片

2)减法         ALU_Operation=4'b0110
a.正-正

05984621abef6f5eH-06985a2f2b2ee9e6H
=403149277082120030-475228919322044902
=-72079642239924872
=feffebf280c08578H

verilog实现适应RISC-V的ALU_第9张图片

b.负-负

fa67b9de541090a2H-f967a5d0d4d1161aH
=-403149277082120030-(-475228919322044902)
=72079642239924872
=0100140d7f3f7a88H

verilog实现适应RISC-V的ALU_第10张图片

c.正-负

05984621abef6f5eH-f967a5d0d4d1161aH
=403149277082120030-(-475228919322044902)
=878378196404164932
=c30a050d71e5944H

verilog实现适应RISC-V的ALU_第11张图片

d.负-正

fa67b9de541090a2H-06985a2f2b2ee9e6H
=(-403149277082120030)-475228919322044902
=-878378196404164932
=f3cf5faf28e1a6bcH

verilog实现适应RISC-V的ALU_第12张图片

3)溢出测试
a.正+正

7fffffffffffffffH+0000000000000009H,结果一定会大于2^64-1,发生溢出
Overflow位置1

verilog实现适应RISC-V的ALU_第13张图片

b.负+负

8000000000000001H+fffffffffffffff7H,结果一定会小于-2^64,发生溢出
Overflow位置1

verilog实现适应RISC-V的ALU_第14张图片

c.正-负

7fffffffffffffffH-fffffffffffffff7H,结果一定会大于2^64-1,发生溢出
Overflow位置1

verilog实现适应RISC-V的ALU_第15张图片

d.负-正

8000000000000001H-0000000000000009H,结果一定会小于-2^64,发生溢出
Overflow位置1

verilog实现适应RISC-V的ALU_第16张图片

2.逻辑运算

initial
begin
    ALU_DA=64'h8452ba5cafe8cca8;
    ALU_DB=64'h2baef5fa56abafba;
    ALU_Operation=4'b0000;
end
1)与         ALU_Operation=4'b0000

verilog实现适应RISC-V的ALU_第17张图片

2)或         ALU_Operation=4'b0001

verilog实现适应RISC-V的ALU_第18张图片

3)或非         ALU_Operation=4'b1100

verilog实现适应RISC-V的ALU_第19张图片

3.小于比较置位         ALU_Operation=4'b0111

1)减法无溢出时的判断

0452ba5cafe8cca8 H < 7baef5fa56abafba H,result = 64‘b 1

verilog实现适应RISC-V的ALU_第20张图片

7452ba5cafe8cca8 H > 0baef5fa56abafba H,result = 64‘b 0

verilog实现适应RISC-V的ALU_第21张图片

2)减法溢出时的判断

7fffffffffffffff H > 8000000000000009 H,result = 64‘b 0

verilog实现适应RISC-V的ALU_第22张图片

8000000000000009 H < 7fffffffffffffff H,result = 64‘b 1

verilog实现适应RISC-V的ALU_第23张图片

至此,仿真测试结束。

你可能感兴趣的:(RISC-V,CPU,risc-v,硬件工程,fpga开发)