自己动手写CPU(MIPS)----带刷新、暂停的四级流水线8位全加器

代码参考重庆大学计算机组成实验,并且在此基础上添加了刷新和暂停,主要目的是理解一下阻塞流水线。

代码

`timescale 1ns / 1ps
// 带有暂停与刷新功能的八位四级流水线,
module adder8Bits4StepsWithStopAndClear

(
    input  [7 : 0]    num1,
    input  [7 : 0]    num2,
   // 上一位的进位
    input              cin,
    // 输入是否有效
    input              validIn,
    // 刷新
    input              rst,
    // 暂停
    input              stop,
    input              clk,
    input              outAllow,
    // 判断输出是否有效
    output wire         validOut,
    output wire         count,
    output wire [7 : 0] sum
);
    reg count1, count2, count3;  
	// 记录每一层是否有效
    reg pipe1Valid;
    reg pipe2Valid;
    reg pipe3Valid;
    reg pipe4Valid;
    // 第一级流水
    reg [1:0] sum1;
	
    // 控制变量:和之前的一样
    // 表示pipe1能否被上一级刷新
    wire   pipe1AllowIn;
    // 表示pipe1是否可以用于刷新下一级
    wire   pipe1ReadyGo;
    // 表示pipe1能否进入pipe2
    wire   pipe1ToPipe2Valid;
	
	//第二级流水
	reg [3:0] sum2;
    wire   pipe2AllowIn;
    wire   pipe2ReadyGo;
    wire   pipe2ToPipe3Valid;
	
	//第三级流水
	reg [5:0] sum3;
    wire   pipe3AllowIn;
    wire   pipe3ReadyGo;
    wire   pipe3ToPipe4Valid;
	
	//第四级流水
	wire pipe4AllowIn;
    wire pipe4ReadyGo;
    reg [7 : 0]sum4;
    reg        count4;
	
    // 如果没有暂停,那么就可以Go
    assign pipe1ReadyGo = !stop;
    // 如果pipe1中的值已经无效,或者这一轮一定会传给下一个,那么就可以进行接收
    assign pipe1AllowIn = ! pipe1Valid || pipe1ReadyGo && pipe2AllowIn;
    // 如果pipe1有效,并且pipe1可以进行传输,那么pipe1ToPipe2Valid可以进行。
    assign pipe1ToPipe2Valid = pipe1Valid && pipe1ReadyGo;
	
    // 是否有效
    always @ (posedge clk) begin
        // 如果需要刷新,那么pipe1Valid 变为0,表示pipe1中的值不再有效
        if( rst ) begin
            pipe1Valid <= 1'b0;
        end
        // 不需要刷新,并且pipe1可以进行刷新
        // 如果输入端有输入,就代表下一个状态pipe1Valid的值有效
        // 如果无输入,就代表下一个状态无效
        else if(pipe1AllowIn)begin
            pipe1Valid <= validIn;
        end
        // 如果输入值有效,并且pipe1可以读入,那么就从输入端进行读入
        if(validIn && pipe1AllowIn)begin
           {count1, sum1} <= {1'b0, num1[1:0]} + {1'b0, num2[1:0]} + cin;
        end
    end
	
    // 第二级流水
    assign pipe2ReadyGo = !stop;
    assign pipe2AllowIn = ! pipe2Valid || pipe2ReadyGo && pipe3AllowIn;
    assign pipe2ToPipe3Valid = pipe2Valid && pipe2ReadyGo;

    always @ (posedge clk) begin
        if( rst ) begin
            pipe2Valid <= 1'b0;
        end
        else if(pipe2AllowIn)begin
            pipe2Valid <= pipe1ToPipe2Valid;
        end
        if(pipe1ToPipe2Valid && pipe2AllowIn)begin
           {count2, sum2} <= {{1'b0, num1[3:2]} + {1'b0, num2[3:2]} + count1, sum1};
        end
    end
	
    // 第三级流水	
    assign pipe3ReadyGo = !stop;
    assign pipe3AllowIn = ! pipe3Valid || pipe3ReadyGo && pipe4AllowIn;
    assign pipe3ToPipe4Valid = pipe3Valid && pipe3ReadyGo;
	
    always @ (posedge clk) begin
        if( rst ) begin
            pipe3Valid <= 1'b0;
        end
        else if(pipe2AllowIn)begin
            pipe3Valid <= pipe2ToPipe3Valid;
        end
        if(pipe2ToPipe3Valid && pipe3AllowIn)begin
            {count3, sum3} <= {{1'b0, num1[5:4]} + {1'b0, num2[5:4]} + count2, sum2};
        end
    end
	
    // 第四级流水	
    // 一样一样的
    assign pipe4ReadyGo = !stop;
    assign pipe4AllowIn = ! pipe4Valid || pipe4ReadyGo && outAllow;

    always @(posedge clk)begin
        if( rst ) begin
            pipe4Valid <= 1'b0;
        end
        else if(pipe3AllowIn)begin
            pipe4Valid <= pipe3ToPipe4Valid;
        end
        if(pipe3ToPipe4Valid && pipe4AllowIn)begin
            {count4, sum4} <= {{1'b0, num1[7:6]} + {1'b0, num2[7:6]} + count3, sum3};
        end
    end
	
    assign validOut = pipe4Valid && pipe4ReadyGo;
    assign sum = sum4;
    assign count = count4;
	
endmodule

仿真文件verilog代码

`timescale 1ns / 1ps



// 测试最后一个模型

module finalSim();

    reg  [7 : 0]    num1;
    reg  [7 : 0]    num2;
    // 上一位的进位
    reg              cin;
    // 输入是否有效
    reg              validIn;
    // 刷新
    reg              rst;
    // 暂停
    reg              stop;
    reg              clk;
    reg              outAllow;
    // 判断输出是否有效
    wire         validOut;
    wire         count;
    wire [7 : 0] sum;
    adder8Bits4StepsWithStopAndClear test1(
		num1,
		num2, 
		cin, 
		validIn,
		rst, 
		stop,
		clk, 
		outAllow, 
		validOut,
		count, 
		sum
	);

    initial begin
        num1 = 8'd1;
        num2 = 8'd1;
        cin  = 1'd0;
        validIn = 1'd1;
        rst = 1'd0;
        stop = 1'd0;
        clk = 1'd0;
        outAllow = 1'd1;
        # 30 rst = 1'b1;
        # 30 rst = 1'b0;
    end

    always # 5 begin
        clk = ~ clk;
    end

    always # 10 begin
        stop = ~ stop;
    end
	
endmodule

仿真结果分析

在分析前首先应该知道四级流水线的8位全加器,完成整个的运算需要4个时钟周期。
一、只添加周期暂停的结果如下,可以发现当stop信号为0时,即正常运行时,4个时钟周期完成运算。

在这里插入图片描述
二、当加入刷新和暂停时。可以看到复位的加入直接重新开始计算,并且在不暂停的4个时钟周期后正常输出数据。
在这里插入图片描述
当然大家也可以修改复位和暂停来看一下仿真的结果。主要理解复位和暂停的含义,和读懂代码。

参考

重庆大学计算机组成实验
lvyufeng@cqu.edu.cn

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kelinnn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值