valid_ready握手机制

我是从牛客网上第一次接触valid_ready机制,想总结这两天自己解题的思路。

VL31

描述
实现串行输入数据累加输出,输入端输入8bit数据,每当模块接收到4个输入数据后,输出端输出4个接收到数据的累加结果。输入端和输出端与上下游的交互采用valid-ready双向握手机制。要求上下游均能满速传输时,数据传输无气泡,不能由于本模块的设计原因产生额外的性能损失。

电路的接口如下图所示。valid_a用来指示数据输入data_in的有效性,valid_b用来指示数据输出data_out的有效性;ready_a用来指示本模块是否准备好接收上游数据,ready_b表示下游是否准备好接收本模块的输出数据;clk是时钟信号;rst_n是异步复位信号。
在这里插入图片描述
在这里插入图片描述

握手协议:

握手指的是两个设备之间通信的一种方式,用来通信的信号就是握手信号。最简单的握手信号是valid和ready,也可以叫request和grant。假设设备1向设备2发送数据,设备1不知道设备2什么时候可以接收数据,设备2也不知道设备1什么时候会发送数据,那么它们之间如果用握手通信可能是这样的顺序:

1、设备1将valid信号置1,告诉设备2,数据准备就绪了,请查收

2、设备2此刻正处于忙碌状态无法接收数据,设备2将ready信号保持为0

3、设备2空闲了,将ready信号置1接收设备1的数据

4、设备1看到设备2的ready为1,它知道设备2已经接收好数据了,将valid置0同时撤销数据,准备下一次发送。

可以看到因为有握手机制,可以确保数据的正确传输,不会丢失。跨时钟域的握手设计就是利用握手控制这种优势,从而避免因为跨时钟域引起的数据传输错误。

解题

此题目中描述的时主机和从机交换数据中间的一个握手bridge
在这里插入图片描述
当valid_a&&ready_a = 1时,表示上游数据成功的被bridge接收到
当valid_b&&ready_b = 1时,表示bridge发送的数据被下游设备成功接收到
注意:ready_a和valid_b信号都是根据其他信号来产生的。

wire ready_a
1、当下游设备表示可以接收数据时(即ready_b = 1),此时bridge也应该可以接收数据,其输出的ready_a拉高
2、当valid_b拉低时,表示bridge还没有准备好发送数据,说明此时bridge正在接收数据,ready_a=1

assign ready_a =(ready_b || !valid_b)?1'b1:1'b0;

reg valid_b
valid_b在时序模块中被赋值,在时序电路图中data_out=10时,valid_b=1
即,当bridge接收到了4个数据后,valid_b拉高,直到数据被下游设备成功接收到,即valid_b&&ready_b = 1后,valid_b立马拉低,data_out立即接收下一轮的第一个数据,可满足数据传输的过程中无气泡

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        valid_b <= 1'b0;
    else begin
        if(ready_a && valid_a && cnt==2'd3)
            valid_b<=1'b1;
        else if(valid_b && ready_b)
            valid_b<=1'b0;           
    end
   end

reg [9:0]data_out
data_out在时序逻辑块中被赋值,当valid_a&&ready_a = 1时,数据成功被接收到data_out中,当cnt=3时,表示4个数据被成功接收,cnt=0时,表示开始下一轮数据传输

   always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        data_out <= 'b0;
    end
    else begin
        if(ready_a && valid_a && cnt == 2'd0)
            data_out <= data_in;
        else if(ready_a && valid_a)
            data_out <= data_in + data_out;
        else
            data_out<=data_out;
    end
   end 
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个基本的valid-ready握手协议的Verilog代码实现,如下所示: ```verilog module valid_ready_handshake ( input logic clk, input logic reset, input logic valid_in, output logic ready_out, output logic valid_out ); // 用于存储当前的握手状态 typedef enum logic [1:0] { IDLE = 2'b00, // 空闲状态 READY = 2'b01, // 准备状态 ACK = 2'b10 // 确认状态 } handshake_state_t; // 定义握手状态变量并初始化为空闲状态 logic [1:0] handshake_state = IDLE; // 当 valid_in 信号变成高电平并且当前状态为空闲状态时,进入准备状态 always_ff @(posedge clk) begin if (reset) begin handshake_state <= IDLE; end else begin case (handshake_state) IDLE: begin if (valid_in) begin handshake_state <= READY; end end READY: begin if (ready_out) begin handshake_state <= ACK; end else if (!valid_in) begin handshake_state <= IDLE; end end ACK: begin if (!valid_in) begin handshake_state <= IDLE; end end endcase end end // 根据当前状态输出 valid_out 和 ready_out 信号 assign valid_out = (handshake_state == READY); assign ready_out = (handshake_state == ACK); endmodule ``` 这个Verilog模块实现了一个简单的 valid-ready 握手协议,其中包含了三种状态:IDLE(空闲状态)、READY(准备状态)和ACK(确认状态)。当输入信号 valid_in 变成高电平时,模块将进入准备状态,此时它会等待输出信号 ready_out 变成高电平。当 ready_out 变成高电平时,模块将进入确认状态,此时它会等待 valid_in 信号变成低电平。一旦 valid_in 信号变成低电平,模块将重新进入空闲状态。 请注意,这只是一个基本的实现,您可以根据您的具体需求进行修改和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值