3.22【计组】 流水线加法器

发布于:2024-12-08 ⋅ 阅读:(178) ⋅ 点赞:(0)

'实验一

`timescale 1ns / 1ps

/* ALU模块实现两个32bit数的add、sub、and、or、not、slt功能,
但由于Nexy7输入口限制,将num1简化为8位,在过程中再extend成32位,num2作为内部wire自行赋值,此处赋为5
由于最后的结果在top.v中以七段数码管显示,32位结果不用以led在nexy4显示,因此输出32位结果没有问题*/

module alu(
    input wire [2:0] op,
    input wire [7:0] num1,
    output reg [31:0] result
    );
    wire [31:0] num2;
    wire [31:0] sign_extend_num1;
    assign num2=32'h0000_0001;
    assign sign_extend_num1={24'h0,num1};
    
    always@(*)begin
        case(op)
            3'b000:result=sign_extend_num1+num2;
            3'b001:result=sign_extend_num1-num2;
            3'b010:result=sign_extend_num1&num2;
            3'b011:result=sign_extend_num1|num2;
            3'b100:result=~sign_extend_num1;
            3'b101:begin
                if(sign_extend_num1<num2)   result=32'h0000_0001;
                else                        result=32'h0000_0000;
            end
            default:result=32'hxxxx_xxxx;
        endcase
    end
    
endmodule
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 [3: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
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
module top(
    input wire [2:0] op,    //手动输入alu
    input wire [7:0] num1,  //手动输入alu
    input wire clk,reset,   //板子上clk、手动rst输入display
    output wire [6:0]seg,   //display输出
    output wire [7:0]ans     //display输出
    );
    wire [31:0] result;      //alu输出进入display
    alu gate1(op,num1,result);
    display gate2(clk,reset,result,seg,ans);
    
endmodule

流水线加法器

二级流水线就是说把八位的加法分为两半去进行,即前一半和后一半,在前一半里有输入信号cin,后一半里接收前一半的进位信号count_temp

这个逗号就是说把两部分并在了一起,前一部分是4位的,后一部分也是4位的,所以连起来就是一个8位的,即最终的结果

至于4级流水其,就是将其分为4段,每段管两位的加法,然后一级一级的并起来,最后合起来就是8位的结果

如果被暂停的话,就向下一级传Z;刷新的话就是全部置0

这个是说一共32位,然后每算一级,就从最低位截取8位,表示这8位已经被计算,然后去记录哪些还没被计算的结果

sum2[7:0]<=sum1就是说直接继承上一级流水线的前8位结果

然后再计算的时候,是记录缓存里的tmpa1的前8位,然后是让未计算的再更新

先判断是否暂停,如果暂停的话就进位和结果都为z,然后当前级下的temp也都为z

接下来判断是否刷新,如果刷新就进位,结果都刷新,temp也刷新

接下来就是正常运行,如果可以的话,判断上一级进位是否传来一个z,如果传来一个z就说明上一级暂停了,那么这一位也要跟着暂停,进位之类的全都设置为z

不然就把已计算出的位数累加到寄存器上,然后记录本流水线上的结果

仿真

这个就是说每25ns翻转一次,那么就是500ns为10个周期,50ns为一个周期


网站公告

今日签到

点亮在社区的每一天
去签到