小白速通:Verilog流水线实现及时序分析

目录

题目:

verilog中,y=(a+b+c+d)*e,时钟频率为50Mhz,用流水线的形式表示,并说明运算完需要多少ns?

图片帮助理解:T1-T4只能做1辆车,但是T4后,每个时钟周期就能做一辆车(如果没有流水线,就每做1辆车都需要4个T的时间)

在Verilog中,将表达式 y=(a+b+c+d)*e 用流水线形式实现,可以分为多个阶段,每个阶段对应一个时钟周期。

流水线设计可以提高电路的吞吐量,但会增加延迟(latency)。下面是具体实现及时序分析。

流水线实现:

将该表达式分为3个流水线阶段:

  1. 第一阶段:计算 a+b 和 c+d
  2. 第二阶段:计算 (a+b)+(c+d)
  3. 第三阶段:计算 ((a+b)+(c+d))*e

代码实现:

c 复制代码
module pipeline_mult (
    input wire clk,         // 时钟信号,50MHz
    input wire rst_n,       // 复位信号,低电平有效
    input wire [7:0] a,     // 假设都是8位输入
    input wire [7:0] b,
    input wire [7:0] c, 
    input wire [7:0] d,
    input wire [7:0] e,
    output reg [15:0] y     // 输出可能需要更宽的位宽
);

    // 第一级流水线寄存器
    reg [8:0] sum_ab;      // a+b的结果,需要多一位防止溢出
    reg [8:0] sum_cd;      // c+d的结果
    reg [7:0] e_reg1;      // 保存e的值传递到下一级

    // 第二级流水线寄存器
    reg [9:0] sum_abcd;    // (a+b)+(c+d)的结果
    reg [7:0] e_reg2;      // 保存e的值传递到下一级

    // 第一级流水线
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            sum_ab <= 9'b0;
            sum_cd <= 9'b0;
            e_reg1 <= 8'b0;
        end else begin
            sum_ab <= a + b;
            sum_cd <= c + d;
            e_reg1 <= e;    // 将e传递到下一级
        end
    end

    // 第二级流水线
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            sum_abcd <= 10'b0;
            e_reg2 <= 8'b0;
        end else begin
            sum_abcd <= sum_ab + sum_cd;
            e_reg2 <= e_reg1;  // 将e传递到下一级
        end
    end

    // 第三级流水线 - 最终结果
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            y <= 16'b0;
        end else begin
            y <= sum_abcd * e_reg2;  // 最终的乘法计算
        end
    end

endmodule

时序分析:时钟频率为50MHz

意味着时钟周期为:

T = 1/f = 1/(50*10^6) = 20 ns

在这个流水线设计中:

第一个输入需要经过3个时钟周期(3级流水线)才能产生有效输出;单次计算的延迟(latency)为:3 * 20 ns = 60 ns ;但一旦流水线填满,之后每个时钟周期都会产生一个新的结果(吞吐量为每20ns一个结果) 。因此,对于单个计算实例,从输入到计算完成需要60 ns的时间。但是流水线的优势在于可以同时处理多个计算实例,每20 ns就能输出一个结果。
给小白,解释一下这个疑问:

c 复制代码
Clock       : |¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|
Time (ns)   :  0  20  40  60  80 100 120 140 160 180 200 220

输入数据:
a           : |10 |  5|  8|   |   |   |   |   |   |   |   |   |   |   |   |
b           : |20 | 15| 12|   |   |   |   |   |   |   |   |   |   |   |   |
c           : |30 | 25| 16|   |   |   |   |   |   |   |   |   |   |   |   |
d           : |40 | 35| 24|   |   |   |   |   |   |   |   |   |   |   |   |
e           : | 2 |  3|  4|   |   |   |   |   |   |   |   |   |   |   |   |

第一级流水线:
sum_ab      : |   | 30| 20| 20|   |   |   |   |   |   |   |   |   |   |   |
sum_cd      : |   | 70| 60| 40|   |   |   |   |   |   |   |   |   |   |   |
e_reg1      : |   |  2|  3|  4|   |   |   |   |   |   |   |   |   |   |   |

第二级流水线:
sum_abcd    : |   |   |100| 80| 60|   |   |   |   |   |   |   |   |   |   |
e_reg2      : |   |   |  2|  3|  4|   |   |   |   |   |   |   |   |   |   |

输出结果:
y           : |   |   |   |200|240|240|   |   |   |   |   |   |   |   |   |
							↑   ↑   ↑
						数据1 数据2 数据3

看完这2个图,你应该大致明白了,不明白的话,继续看下面这个分析:

详细时序分析:

数据1: a=10, b=20, c=30, d=40, e=2

  1. 时钟周期1 (0-20ns):
  • 输入数据: a=10, b=20, c=30, d=40, e=2
  • 寄存器尚未更新
  1. 时钟周期2 (20-40ns):
  • 第一级流水线:
    • sum_ab = 10 + 20 = 30
    • sum_cd = 30 + 40 = 70
    • e_reg1 = 2
    • 其他级别未更新
  1. 时钟周期3 (40-60ns):
  • 第二级流水线:
    • sum_abcd = 30 + 70 = 100
    • e_reg2 = 2
    • 第三级流水线尚未更新
  1. 时钟周期4 (60-80ns):
  • 输出结果:
    • y = 100 * 2 = 200 (实例1的最终结果)

数据2: a=5, b=15, c=25, d=35, e=3

  1. 时钟周期2 (20-40ns):
    • 输入数据: a=5, b=15, c=25, d=35, e=3
    • 寄存器尚未更新
  2. 时钟周期3 (40-60ns):
    • 第一级流水线:
    • sum_ab = 5 + 15 = 20
    • sum_cd = 25 + 35 = 60
    • e_reg1 = 3
    • 其他级别未更新
  3. 时钟周期4 (60-80ns):
    • 第二级流水线:
    • sum_abcd = 20 + 60 = 80
    • e_reg2 = 3
    • 第三级流水线尚未更新
  4. 时钟周期5 (80-100ns):
    • 输出结果:
    • y = 80 * 3 = 240 (数据2的最终结果)

数据3: a=8, b=12, c=16, d=24, e=4

  1. 时钟周期3 (40-60ns):
    • 输入数据: a=8, b=12, c=16, d=24, e=4
    • 寄存器尚未更新
  2. 时钟周期4 (60-80ns):
    • 第一级流水线:
    • sum_ab = 8 + 12 = 20
    • sum_cd = 16 + 24 = 40
    • e_reg1 = 4
    • 其他级别未更新
  3. 时钟周期5 (80-100ns):
    • 第二级流水线:
    • sum_abcd = 20 + 40 = 60
    • e_reg2 = 4
    • 第三级流水线尚未更新
  4. 时钟周期6 (100-120ns):
    • 输出结果:
    • y = 60 * 4 = 240 (数据3的最终结果)

流水线效率分析

  1. 延迟 (Latency):
  • 每个计算实例从输入到输出需要3个时钟周期 = 60 ns
  1. 吞吐量 (Throughput):
  • 流水线满载后,每20 ns产生一个结果
  • 3个计算实例总共需要时间 = 60 ns (首个结果) + 40 ns (接下来2个结果) = 100 ns
  • 如果是没有流水线的设计,需要 3 * 60 ns = 180 ns
  1. 性能提升:
  • 流水线设计对于处理大量连续数据时,性能提升明显
  • 在这个例子中,处理3个连续实例的时间从180 ns减少到了100 ns,提升约44%
    这种波形图清晰地展示了流水线的工作原理,显示了每个计算实例如何逐级推进,最终产生结果,以及多个实例如何在流水线中重叠执行,提高总体处理效率。
相关推荐
肯德基疯狂星期四-V我508 小时前
【FPGA】状态机思想实现LED流水灯&HDLbits组合逻辑题训练
fpga开发·verilog·de2-115
乌恩大侠12 小时前
【调研】YOLO算法在FPGA/ZYNQ上的部署与加速
yolo·fpga开发
Abcdsa15 小时前
labview RT FPGA使用技巧 基础知识
fpga开发·labview
暴富奥利奥19 小时前
FPGA学习(四)——状态机重写LED流水灯并仿真
学习·fpga开发
岁月磨吾少年志21 小时前
【FPGA开发】利用状态机思想点亮流水灯/初学hdlbitsFPGA教程网站
fpga开发
建筑玩家21 小时前
FPGA实现按键切换流水灯不同亮灭模式
单片机·fpga开发
鸡精拌饭1 天前
FPGA练习
fpga开发
可编程芯片开发1 天前
基于FPGA的特定序列检测器verilog实现,包含testbench和开发板硬件测试
fpga开发·verilog·特定序列检测
Cynthia的梦1 天前
FPGA——FPGA状态机实现流水灯
fpga开发