0
点赞
收藏
分享

微信扫一扫

verilog实现简单算术逻辑单元ALU

根据mips指令集实现能进行12种算数逻辑运算单元,不支持例外处理。
模块输入包括两个操作数和选择进行何种运算的 片选信号(alu_control) 和一个结果输出端口。结果输出端用了一个无优先级的多路选择器实现结果选择。

12种运算类型分别为:

  1. 加法
  2. 减法
  3. 有符号比较小于置为1
  4. 无符号比较小于置为1
  5. 与,非或,或,异或四种逻辑运算
  6. 逻辑左、右移
  7. 算数右移
  8. 置寄存器高16位

具体代码如下:

module alu (
    input   [11:0] alu_control,
    input   [31:0] alu_src1,
    input   [31:0] alu_src2,
    output  [31:0] alu_result
); 
    //control
    wire op_add     = alu_control[0];
    wire op_sub     = alu_control[1];
    wire op_slt     = alu_control[2];
    wire op_sltu    = alu_control[3];
    wire op_and     = alu_control[4];
    wire op_nor     = alu_control[5];
    wire op_or      = alu_control[6];
    wire op_xor     = alu_control[7];
    wire op_sll     = alu_control[8];
    wire op_srl     = alu_control[9];
    wire op_sra     = alu_control[10];
    wire op_lui     = alu_control[11];

    //result
    wire [31:0]     add_sub_res;
    wire [31:0]     slt_res;
    wire [31:0]     sltu_res;
    wire [31:0]     and_res;
    wire [31:0]     nor_res;
    wire [31:0]     or_res;
    wire [31:0]     xor_res;
    wire [31:0]     sll_res;
    wire [31:0]     srl_res;
    wire [31:0]     sra_res;
    wire [31:0]     lui_res;

    //logic
    assign  and_res = alu_src1 & alu_src2;
    assign  or_res  = alu_src1 | alu_src2;
    assign  xor_res = alu_src1 ^ alu_src2;
    assign  nor_res = ~or_res;
    assign  lui_res = {alu_src2[15:0], 16'b0};

    //adder
    wire    [31:0] adder1;
    wire    [31:0] adder2;
    wire           adder_cin;
    wire    [31:0] adder_res;
    wire           adder_cout;
    assign  adder1      = alu_src1;
    assign  adder2      = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2;
    assign  adder_cin   = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
    assign  {adder_cout,adder_res} = adder1 + adder2 + adder_cin;

    assign  add_sun_res = adder_res;

    //slt && sltu
    assign slt_res [31:1] = 31'b0;
    assign sltu_res[31:1] = 31'b0;
    assign sltu_res[0]    = ~adder_cout;
    assign slt_res [0]    = (alu_src1[31] & ~alu_src2[31])
                          | ( ~(alu_src1[31] ^ alu_src2[31]) & adder_res[31]) ;
    
    //sll && srl && sra
    assign sll_res = alu_src2 << alu_src1[4:0];
    assign srl_res = alu_src2 >> alu_src1[4:0];
    assign sra_res = ($signed(alu_src2)) >>> alu_src1[4:0];

    //cout_result
    assign alu_result = ({32{op_add | op_sub}} & add_sub_res)
                      | ({32{op_slt         }} & slt_res)
                      | ({32{op_sltu        }} & sltu_res)
                      | ({32{op_and         }} & and_res)
                      | ({32{op_nor         }} & nor_res)
                      | ({32{op_or          }} & or_res)
                      | ({32{op_xor         }} & xor_res)
                      | ({32{op_sll         }} & sll_res)
                      | ({32{op_srl         }} & srl_res)
                      | ({32{op_sra         }} & sra_res)
                      | ({32{op_lui         }} & lui_res);
endmodule

举报

相关推荐

0 条评论