【牛客】VL60 使用握手信号实现跨时钟域数据传输

题目描述

  分别编写一个数据发送模块和一个数据接收模块,模块的时钟信号分别为clk_a,clk_b。两个时钟的频率不相同。数据发送模块循环发送0-7,在每个数据传输完成之后,间隔5个时钟,发送下一个数据。请在两个模块之间添加必要的握手信号,保证数据传输不丢失。
  模块的接口信号图如下:
在这里插入图片描述

data_req和data_ack的作用说明:
  data_req表示数据请求接受信号。当data_out发出时,该信号拉高,在确认数据被成功接收之前,保持为高,期间data应该保持不变,等待接收端接收数据。
  当数据接收端检测到data_req为高,表示该时刻的信号data有效,保存数据,并拉高data_ack。
  当数据发送端检测到data_ack,表示上一个发送的数据已经被接收。撤销data_req,然后可以改变数据data。等到下次发送时,再一次拉高data_req。

输入描述:
   clk_a:发送端时钟信号
   clk_b:接收端时钟信号
   rst_n:复位信号,低电平有效
   data_ack:数据接收确认信号

输出描述:
   data:发送的数据
   data_req:请求接收数据

自解

`timescale 1ns/1ns
// 20240301
module data_driver(
	input   clk_a,
	input   rst_n,

	input           data_ack,
	output reg [3:0]data    ,
	output reg      data_req
	);

    initial begin
        data     = 4'b0;
        data_req = 1'b0;
    end

/*********  CDC processing start  ***********/

    reg data_ack_d1_r, data_ack_d2_r;

    always @(posedge clk_a) begin
        data_ack_d1_r <= data_ack;
        data_ack_d2_r <= data_ack_d1_r;
    end

/*********  CDC processing end  *************/

    reg [1:0] cs = 2'h0, ns;

    reg [3:0] data_r = 4'd0;

    reg [2:0]   timeout_cnt_r   = 3'd0;
    reg         timeout_flag_r  = 1'b0;

    always @(posedge clk_a, negedge rst_n) begin
        if (~rst_n) begin
            cs <= 2'h0;
        end else begin
            cs <= ns;
        end
    end

    always @(*) begin
        case (cs)
        2'h0: begin
            ns = 2'h2;
        end
        2'h1: begin
            if (data_req & data_ack_d2_r) begin
                ns = 2'h2;
            end else begin
                ns = 2'h1;
            end
        end
        2'h2: begin
            if (timeout_flag_r) begin
                ns = 2'h1;
            end else begin
                ns = 2'h2;
            end
        end
        default: begin
            ns = 2'h0;
        end
        endcase
    end

    always @(posedge clk_a) begin
        case (ns)
        default: begin
            data_req    <= 1'b0;
            data        <= 4'd0;
            data_r      <= 4'd0;
        end
        2'h1: begin
            data_req    <= 1'b1;
            data        <= data_r;
            if (data_req & data_ack_d2_r) begin
                data_r  <= data_r + 4'd1;
            end
        end
        2'h2: begin
            data_req    <= 1'b0;
            data        <= data;
            data_r      <= data_r;
        end
        endcase        
    end

    always @(posedge clk_a) begin
        case (ns)
        default: begin
            timeout_cnt_r   <= 3'd0;
            timeout_flag_r  <= 1'b0;
        end
        2'h2: begin
            timeout_cnt_r   <= timeout_cnt_r + 3'd1;
            if (timeout_cnt_r == 3'd4) begin
                timeout_flag_r <= 1'b1;
            end else begin
                timeout_flag_r <= 1'b0;
            end
        end
        endcase
    end

endmodule

module data_receiver(
	input clk_b,
	input rst_n,
	output reg data_ack,
	input [3:0] data,
	input data_req
	);

    initial begin
        data_ack = 1'b0;
    end

/***********  CDC processing start  ************/

    reg [3:0]   data_d1_r, data_d2_r;
    reg         data_req_d1_r, data_req_d2_r;

    always @(posedge clk_b) begin
        data_d1_r <= data;
        data_d2_r <= data_d2_r;
        
        data_req_d1_r <= data_req;
        data_req_d2_r <= data_req_d1_r;
    end

/***********  CDC processing end  *************/

    reg [1:0] cs = 2'h0, ns;

    always @(posedge clk_b, negedge rst_n) begin
        if (~rst_n) begin
            cs <= 2'h0;
        end else begin
            cs <= ns;
        end
    end

    always @(*) begin
        case (cs)
        2'h0: begin
            ns = 2'h1;
        end
        2'h1: begin
            ns = 2'h1;
        end
        default: begin
            ns = 2'h0;
        end
        endcase
    end

    always @(posedge clk_b) begin
        case (ns)
        default: begin
            data_ack <= 1'b0;
        end
        2'h1: begin
            data_ack <= 1'b1;
        end
        endcase
    end

    always @(posedge clk_b) begin
        case (ns)
        2'h1: begin
            if (data_ack & data_req_d2_r) begin
                // data_d2_r validate
            end
        end
        endcase
    end

endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/431450.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)

(vue)el-checkbox 实现展示区分 label 和 value&#xff08;展示值与选中获取值需不同&#xff09; 后端数据 解决方法 在 el-checkbox 标签中间传入要展示的文本即可&#xff0c;代码如下&#xff1a; <el-checkbox-groupv-model"formInline.processFieldList"…

【C语言】指针超级无敌金刚霹雳进阶(但不难,还是基础)

点击这里访问我的博客主页~~ 对指针概念还不太清楚的点击这里访问上一篇指针初阶2.0 上上篇指针初阶1.0 谢谢各位大佬的支持咯 今天我们一起来学习指针进阶内容 指针进阶 一、指针变量1、字符指针变量2、数组指针变量①数组指针变量的定义②数组指针变量的初始化 3、函数指…

代码随想录第50天|● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV

文章目录 ● 123.买卖股票的最佳时机III思路代码一&#xff1a;dp二维数组代码二&#xff1a;四个数存储 ● 188.买卖股票的最佳时机IV思路&#xff1a;代码&#xff1a; ● 123.买卖股票的最佳时机III 思路 dp[i][j]中 i表示第i天&#xff0c;j为 [0 - 4] 五个状态&#xff0…

C++ string类详解及模拟实现

目录 【本节目标】 1. 为什么学习string类&#xff1f; 1.1 C语言中的字符串 1.2 面试题(暂不做讲解) 2. 标准库中的string类 2.1 string类(了解) 2.2 string类的常用接口说明&#xff08;注意下面我只讲解最常用的接口&#xff09; 3. string类的模拟实现 3.1string类常用…

操作系统篇——虚拟内存到底是个啥?

先祝大家春招都过&#xff0c;后台私信我&#xff0c;可免费获得面试宝典&#xff0c;祝大家都和我一样&#xff0c;顺顺利利面大厂!!! 为什么不直接使用物理内存 虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存&#xff08;一个连续完整的…

YOLOv9推理详解及部署实现

目录 前言零、YOLOv9简介一、YOLOv9推理(Python)1. YOLOv9预测2. YOLOv9预处理3. YOLOv9后处理4. YOLOv9推理 二、YOLOv9推理(C)1. ONNX导出2. YOLOv9预处理3. YOLOv9后处理4. YOLOv9推理 三、YOLOv9部署1. 源码下载2. 环境配置2.1 配置CMakeLists.txt2.2 配置Makefile 3. ONNX…

useState多次渲染页面卡顿 useMemo

useState多次渲染页面卡顿 state变化了组件自然应该重新进行渲染&#xff0c;但有时我们并不需要。 React.memo()(useMemo)是一个高阶组件&#xff0c;它接收另一个组件作为参数&#xff0c;并且会返回一个包装过的新组件&#xff0c;包装过的新组件就会具有缓存作用&#xff…

已经连接过github远程库,如何再次推送及删除远程库的内容

基于上次将文件推送到已经建好的github远程库上&#xff0c;此篇文章主要介绍如何再次推送文件去直接已经连接过的远程库&#xff0c;以此如何删除远程库中不想要的文件。 一、推送文件到远程库 1.将所需推送的文件拉入本地库所建的文件夹下&#xff1a;{ex&#xff1a;JVM相…

HTML5:七天学会基础动画网页8

2D缩放:scale scale(x,y) 2D缩放转换&#xff0c;改变元素的宽度和 高度&#xff0c;值为缩放的倍数。 scaleX(n) 2D缩放转换&#xff0c;改变元素的宽度。 scaleY(n) 2D播放转换&#xff0c;改变元素的高度。 跟前面提到的平移同理&#xff0…

Redis 7.0版本主从复制机制

1、引言 Redis是一个开源、高性能、内存键值存储系统&#xff0c;同时也提供了数据结构服务器的功能。它支持五种主要的数据类型&#xff1a;字符串&#xff08;String&#xff09;、哈希表&#xff08;Hashes&#xff09;、列表&#xff08;Lists&#xff09;、集合&#xff…

Vue基础篇

Vue Vue是一套用于构建用户界面的渐进式JavaScript框架 什么是渐进式? Vue可以自底向上逐层地应用; 当构建简单应用时, 只需一个轻量小巧的核心库; 当构建复杂应用时, 可以引入各式各样的Vue插件 Vue具有以下特点: 采用组件化模式, 提高代码复用率且让代码更好维护 声明式编…

软考58-上午题-【数据库】-分布式数据库

一、四个透明 二、四种性质 三、真题 真题1&#xff1a; 真题2&#xff1a; 真题3&#xff1a; 真题4&#xff1a; 真题5&#xff1a;

10亿数据如何快速插入MySQL

最快的速度把10亿条数据导入到数据库,首先需要和面试官明确一下,10亿条数据什么形式存在哪里,每条数据多大,是否有序导入,是否不能重复,数据库是否是MySQL? 有如下约束 10亿条数据,每条数据 1 Kb 数据内容是非结构化的用户访问日志,需要解析后写入到数据库 数据存放在…

Linux笔记--静态库和动态库

库是指在我们的应用中&#xff0c;有一些公共代码是需要反复使用&#xff0c;就把这些代码编译为"库"文件;在链接步骤中&#xff0c;链接器将从库文件取得所需的代码&#xff0c;复制到生成的可执行文件中。 Linux中常见的库文件有两种&#xff0c;一种.a为后缀&…

【力扣白嫖日记】1045.买下所有产品的客户

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1045.买下所有产品的客户 表&#xff1a;Customer 列名类型customer_idintproduct_keyint 该表可能包含重复…

HashData的湖仓一体思考:Iceberg、Hudi特性讲解与支持方案

湖仓一体作为一种新兴的开放式数据管理架构&#xff0c;能够充分发挥数据湖的灵活性、生态丰富以及数据仓库的企业级数据分析能力&#xff0c;已经成为企业建设现代数据平台的热门选择。 在此前的直播中&#xff0c;我们分享了HashData湖仓一体方案架构设计与Hive数据同步。本…

2024金三银四--我们遇到的那些软件测试面试题【功能/接口/自动化/性能等等】

一、面试技巧题(主观题) 序号面试题1怎么能在技术没有那么合格的前提下给面试官留个好印象&#xff1f;2面试时&#xff0c;如何巧妙地避开不会的问题&#xff1f;面试遇到自己不会的问题如何机智的接话&#xff0c;化被动为主动&#xff1f;3对于了解程度的技能&#xff0c;被…

matlab 实现模糊C均值聚类

1. 原理 模糊c均值算法步骤&#xff1a; 1. 设定聚类数目c和加权指数b&#xff1a; 2. 初始化各个聚类中心m 3. 重复下面的运算&#xff0c;直到各个样本的隶属度值稳定&#xff1a;用当前的聚类中心根据下式计算隶属度函数&#xff1a; 用当前的隶属度函数按下式更新计算各…

fastApi笔记12-OAuth2 实现密码哈希与 Bearer JWT 令牌验证

JWT JWT(Json Web Token)是一种可以跨域的认证方案 jwt由三部分构成&#xff1a; 头部header&#xff1a;头部包含算法和token类型 核载payload&#xff1a;这部分用来保存自定义信息 签名signature&#xff1a;使用header和payload以及提供的秘钥&#xff0c;用header指定…

12c 32k strings新特性 varchar2/nvarchar2 32K

12c 32k strings新特性 varchar2/nvarchar2 32K 1、查看 SQL> show parameter MAX_STRING_SIZENAME TYPE VALUE ------------------------------------ ----------- ------------------------------ max_string_size …