MIPS指令的CPU实现:ALU设计

时间:2024-02-01 10:45:34

设计CPU的第一步,设计一个简单的逻辑运算单元ALU。同时对Verilog语言也有一定要求。

一、实验内容

  1. 如图,ALU接受两个N位的输入,得到N位的输出,通过控制信号F决定运算功能。

  2. 将ALU的输出结构与七段数码管显示模块连接,使用实验配置的NEXYS4开发板。
    结构如下:
  3. 编写顶层模块top连接上述模块。
  4. 仿真,编写约束文件,生成二进制文件,在开发板上验证。
    整体难度不大,主要任务就是编写ALU和top,以及约束文件。
    但是这学期之前在摸鱼,这个小实验都没认真弄好。。。地基打不好,CPU肯定写不出来啊。

二、RTL级的部分Verilog代码,也是重点部分

ALU.v

真的很简单,方法两种,一种是always逻辑,一种是assign逻辑。

  1. always:
module ALU(
    input wire [31:0] A,
    input wire[31:0] B,
    input wire [2:0] OP, // 输入用wire
    output reg [31:0] F //输出用寄存器reg
    );
    always @(*) begin
        case(OP)
            3'b000: begin F <= A + B; end //这里实际上连进位都没有考虑
            3'b001: begin F <= A - B; end
            3'b010: begin F <= A & B; end
            3'b011: begin F <= A | B; end
            3'b100: begin F <= ~A; end
            3'b101: begin F <= A<B; end
            default:  begin F <= 0; end
        endcase
    end
endmodule
  1. assign:
    assign相当于连线,一般是将一个变量的值不间断地赋值给另一个变量,所以赋值的类型应用wire。
module ALU(
    input wire [31:0] A,
    input wire[31:0] B,
    input wire [2:0] OP,
    output wire [31:0] F
    );
    assign F = (OP == 3'b000) ? A + B:
                (OP == 3'b001) ? A + B:
                (OP == 3'b010) ? A + B:
                (OP == 3'b011) ? A + B:
                (OP == 3'b100) ? A + B:
                (OP == 3'b101) ? A + B:
                32'b0;
endmodule

数码管显示模块display.v和seg7.v(实验提供)

  1. display.v
module display(
    input wire clk,reset,
    input wire [31:0]s,
    output wire [6:0]seg,
    output reg [7:0]ans
    );
    reg [20:0]count;
    reg [4:0]digit; 
    always@(posedge clk,posedge reset)
    if(reset)  
        count = 0;
    else 
        count = count + 1;
       
    always @(posedge clk)
    case(count[20:18])
        0:begin
            ans = 8'b11111110;
            digit = s[3:0];
        end
        1:begin
            ans = 8'b11111101;
            digit = s[7:4];
        end
        2:begin
            ans = 8'b11111011;
            digit =s[11:8];
        end
        3:begin
            ans = 8'b11110111;
            digit = s[15:12];
        end
         4:begin
             ans = 8'b11101111;
             digit = s[19:16];
         end
         5:begin
             ans = 8'b11011111;
             digit = s[23:20];
         end
         6:begin
             ans = 8'b10111111;
             digit =s[27:24];
         end
         7:begin
             ans = 8'b01111111;
             digit = s[31:28];
         end
    endcase
    
    seg7 U4(.din(digit),.dout(seg));
endmodule
  1. seg7.v
module seg7(
    input wire [3:0]din,
    output reg [6:0]dout
    );
 
    always@(*)
    case(din)
        5'h0:dout = 7'b000_0001;
        5'h1:dout = 7'b100_1111;
        5'h2:dout = 7'b001_0010;
        5'h3:dout = 7'b000_0110;
        5'h4:dout = 7'b100_1100;
        5'h5:dout = 7'b010_0100;
        5'h6:dout = 7'b010_0000;
        5'h7:dout = 7'b000_1111;
        5'h8:dout = 7'b000_0000;
        5'h9:dout = 7'b000_0100;
        5'ha:dout = 7'b000_1000;
        5'hb:dout = 7'b110_0000;
        5'hc:dout = 7'b011_0001;
        5'hd:dout = 7'b100_0010;
        5'he:dout = 7'b011_0000;
        5'hf:dout = 7'b011_1000;
        default:dout = 7'b111_1111;        
    endcase
    
endmodule

top.v

module top(
    input wire clk, rst,
    output wire[6:0] seg,
    output wire[7:0] ans,
    input wire [2:0] op,
    input wire [7:0] num_1
    );
    wire [31:0] f; // f从ALU传给display
    ALU U1(.A({24'b0,num_1}),.B(32'h1),.OP(op),.F(f)); // 输入a为8位扩充至32位,b为固定值32'h1

    display U2(.clk(clk),.reset(rst),.s(f),.ans(ans),.seg(seg));
endmodule

三、存在的问题

  1. 仿真测试中得不到结果,但是下到板子上以后能正常运行

test文件:

module test();
    reg [7:0] num_1;
    reg [2:0] op;
    wire [6:0]seg;
    wire [7:0]ans;
    reg clk,rst;

    always #25 clk = ~clk;

    initial begin
        clk = 1;
        rst = 0;
        num_1 = 8'h 11;
        op = 3'b 111;
        # 100 op = 3'b 000;
        # 100 op = 3'b 001;
        # 100 op = 3'b 010;
        # 100 op = 3'b 011;
        # 100 op = 3'b 100;
        # 100 op = 3'b 101;
    end
    
    top x(
    .clk(clk),
    .rst(rst),
    .seg(seg),
    .ans(ans),
    .num_1(num_1),
    .op(op)
    );
    
endmodule