小白速通: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%
    这种波形图清晰地展示了流水线的工作原理,显示了每个计算实例如何逐级推进,最终产生结果,以及多个实例如何在流水线中重叠执行,提高总体处理效率。
相关推荐
内有小猪卖1 小时前
时序约束 记录
fpga开发
Cao1234567893214 小时前
FPGA时钟设计
fpga开发
JNTeresa7 小时前
锁存器知识点详解
fpga开发
Cao12345678932110 小时前
FPGA基础之基础语法
fpga开发
一大Cpp10 小时前
通过Quartus II实现Nios II编程
fpga开发
7yewh11 小时前
Verilog 语法 (二)
fpga开发
边缘计算社区1 天前
FPGA与边缘AI:计算革命的前沿力量
人工智能·fpga开发
S&Z34631 天前
[官方IP] Shift RAM
网络协议·tcp/ip·fpga开发
S&Z34631 天前
[FPGA Video IP] Video Processing Subsystem
网络协议·tcp/ip·fpga开发·video
FPGA_Linuxer1 天前
FPGA 100G UDP纯逻辑协议栈
网络协议·fpga开发·udp