Xilinx LVDS 接口中的时钟对齐模块的RTL编写

news2024/12/12 11:34:46

本人写的一个时钟对齐的模块,仅供参考

主要原因:
由于 FPGA 内部布局布线所带来的延时,到达 ISERDESE2 相应管脚的帧时钟、位时
钟与数据信号可能不再保持初始的相位关系,从而导致无法得到正确的串并转换数据,所以需
要利用 SelectIO 资源使时钟与数据恢复对应的相位关系

框架模型: LVDS接口模块电路框图
在这里插入图片描述

module clk_align(

	input i_clk_dclk           ,
	input i_rst                ,
	input i_idelay_refclk      , 
	input i_clk_align_rst      ,

	output o_clk_hs            ,
	output o_clk_div           ,
	output o_clk_align_ok      
);

parameter P_WAIT_INIT    = 20 ,
		  P_STABLE_TIME  = 100,
		  P_ALIGN_CNT    = 100;

parameter IDLE                = 0,
		  IDELYCTRL_INIT      = 1,
		  IDLEY_INIT     	  = 2,
		  ISERDES_INIT        = 3,
		  CLOCK_ALIGN_PROCESS = 4,
		  WAIT_DATA_STABLE    = 5,
		  ALIGN_OK            = 6;

wire w_clk_out          ; 
wire idelay_rdy         ;
wire w_dclk_delay       ;
wire [7:0] sample_value ;

reg [2:0] r_custates    ;
reg [2:0] r_nxstates    ;
reg [7:0] r_states_cnt  ;
reg [7:0] r_dclk_data   ;
reg [15:0] r_align_cnt  ;
reg r_clk_align_ok      ;
reg r_f                 ;
reg r_idelay_ctrl_rst   ;
reg r_idelay_rst        ;
reg r_iserds_rst        ;
reg r_idelay_load       ;
reg r_idelay_ce         ;
reg r_idelay_inc        ;

assign o_clk_align_ok = r_clk_align_ok ;

always @ (posedge o_clk_div or posedge i_rst) begin
	if (i_rst)
		r_custates <= IDLE ;
	else
		r_custates <= r_nxstates;
end

always @ (*) begin
	case (r_custates)
		IDLE : begin
						if (r_states_cnt == P_WAIT_INIT)
							r_nxstates = IDELYCTRL_INIT;
						else
							r_nxstates = r_custates;
		end
		IDELYCTRL_INIT : begin
						if (idelay_rdy && r_states_cnt == P_WAIT_INIT)
							r_nxstates = IDLEY_INIT;
						else
							r_nxstates = r_custates;							
		end
		IDLEY_INIT : begin
						if (r_states_cnt == P_WAIT_INIT)
							r_nxstates = ISERDES_INIT;
						else
							r_nxstates = r_custates;		
		end
		ISERDES_INIT : begin
						if (r_states_cnt == P_WAIT_INIT)
							r_nxstates = WAIT_DATA_STABLE;
						else
							r_nxstates = r_custates;	
		end
		CLOCK_ALIGN_PROCESS : begin
						if (r_align_cnt == P_ALIGN_CNT -1)
							r_nxstates = ALIGN_OK;
						else
							r_nxstates = WAIT_DATA_STABLE;			
		end	
		WAIT_DATA_STABLE : begin
						if (r_states_cnt == P_STABLE_TIME -1)
							r_nxstates = CLOCK_ALIGN_PROCESS;
						else
							r_nxstates = r_custates;									
		end	
		ALIGN_OK :begin
						if (i_clk_align_rst)
							r_nxstates = IDLE;
						else
							r_nxstates = r_custates;	
		end
		default : begin
							r_nxstates = IDLE;	
		end
	endcase
end

// states cnt
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_states_cnt <= 0;
	else if (r_custates !=  r_nxstates)
		r_states_cnt <= 0;
	else
		r_states_cnt <= r_states_cnt + 1;		
end

// idely ctrl rst
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_idelay_ctrl_rst <= 0;
	else if (r_custates == IDELYCTRL_INIT && r_states_cnt <= 1)
		r_idelay_ctrl_rst <= 1;
	else
		r_idelay_ctrl_rst <= 0;		
end

//idely rst
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_idelay_rst <= 0;
	else if (r_custates == IDLEY_INIT && r_states_cnt <= 1)
		r_idelay_rst <= 1;
	else
		r_idelay_rst <= 0;		
end

//iserdes rst
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_iserds_rst <= 0;
	else if (r_custates == ISERDES_INIT && r_states_cnt <= 1)
		r_iserds_rst <= 1;
	else
		r_iserds_rst <= 0;		
end

//r_idelay_load
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_idelay_load <= 0;
	else if (r_custates == IDLEY_INIT && r_states_cnt == 10)
		r_idelay_load <= 1;
	else
		r_idelay_load <= 0;		
end

// idelay ce and inc
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) begin
		r_idelay_ce  <= 0;
		r_idelay_inc <= 0;
	end else if (r_custates == CLOCK_ALIGN_PROCESS && sample_value == 8'h00) begin
		r_idelay_ce  <= 1;
		r_idelay_inc <= 1;
	end else if (r_custates == CLOCK_ALIGN_PROCESS && sample_value == 8'hff) begin
		r_idelay_ce  <= 1;
		r_idelay_inc <= 0;
	end else begin
		r_idelay_ce  <= 0;
		r_idelay_inc <= 0;
	end	
end

// compare
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_dclk_data <= 0;
	else
		r_dclk_data <= sample_value;
end

always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_align_cnt <= 0;
	else if (r_custates == CLOCK_ALIGN_PROCESS && r_align_cnt == P_ALIGN_CNT - 1)
		r_align_cnt <= 0;
	else if ( r_custates == CLOCK_ALIGN_PROCESS && r_f)
		r_align_cnt <= r_align_cnt + 1;
	else
		r_align_cnt <= r_align_cnt;
end

// 数据不相等的标记
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_f <= 0;
	else if (r_custates == CLOCK_ALIGN_PROCESS)
		r_f <= 0;		
    else if (r_dclk_data != sample_value)
		r_f <= 1;
	else
		r_f <= r_f;
end

// output clk_align flag
always @(posedge o_clk_div or posedge i_rst) begin 
	if (i_rst) 
		r_clk_align_ok <= 0;
	else if (r_custates != ALIGN_OK)
		r_clk_align_ok <= 0;
	else if (r_custates == ALIGN_OK)
		r_clk_align_ok <= 1;
	else
		r_clk_align_ok <= r_clk_align_ok;
end

/*-----------------------------------------------------XILINX PRIMITIVE-----------------------------------------------------------*/

	
//	(*IODELAY_GROUP = clk*) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
	IDELAYCTRL IDELAYCTRL_inst (
		.RDY(idelay_rdy), // 1-bit output: Ready output
		.REFCLK(i_idelay_refclk), // 1-bit input: Reference clock input
		.RST(r_idelay_ctrl_rst) // 1-bit input: Active high reset input
	);
	
	//(* IODELAY_GROUP = clk*) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
	IDELAYE2 #(
		.CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE)
		.DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN)
		.HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
		.IDELAY_TYPE("VARIABLE"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
		.IDELAY_VALUE(9), // Input delay tap setting (0-31)
		.PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE
		.REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
		.SIGNAL_PATTERN("CLOCK") // DATA, CLOCK input signal
	)
	IDELAYE2_inst (
		.REGRST(r_idelay_rst), // 1-bit input: Active-high reset tap-delay input
		.C(o_clk_div), // 1-bit input: Clock input
		.CE(r_idelay_ce), // 1-bit input: Active high enable increment/decrement input
		.INC(r_idelay_inc), // 1-bit input: Increment / Decrement tap delay input
		.LD(r_idelay_load), // 1-bit input: Load IDELAY_VALUE input
		.DATAIN(1'b0), // 1-bit input: Internal delay data input
		.IDATAIN(i_clk_dclk), // 1-bit input: Data input from the I/O
		.DATAOUT(w_dclk_delay), // 1-bit output: Delayed data output
		.LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input
		.CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input
		.CNTVALUEIN(5'b00000), // 5-bit input: Counter value input
		.CNTVALUEOUT() // 5-bit output: Counter value output
	);
	
	BUFIO BUFIO_inst (
	.O(o_clk_hs), // 1-bit output: Clock output (connect to I/O clock loads).
	.I(w_clk_out) // 1-bit input: Clock input (connect to an IBUF or BUFMR).
	);
	
	BUFR #(
		// .BUFR_DIVIDE("3"), // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8"        3div,clk_out_div=100M
        .BUFR_DIVIDE("4"), // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8"        4div,clk_out_div=100M
		.SIM_DEVICE("7SERIES") // Must be set to "7SERIES"
	)
	BUFR_inst (
		.O(o_clk_div), // 1-bit output: Clock output port
		.CE(1'b1), // 1-bit input: Active high, clock enable (Divided modes only)
		//.CLR(1'b0), // 1-bit input: Active high, asynchronous clear (Divided modes only)
		.CLR(i_rst), // 1-bit input: Active high, asynchronous clear (Divided modes only)
		.I(w_clk_out) // 1-bit input: Clock buffer input driven by an IBUF, MMCM or local interconnect
	);
	
	ISERDESE2 #(
		.SERDES_MODE("MASTER"), // MASTER, SLAVE
		.INTERFACE_TYPE("NETWORKING"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
		.IOBDELAY("IBUF"), // NONE, BOTH, IBUF, IFD
		.DATA_RATE("SDR"), // DDR, SDR
		.DATA_WIDTH(8), // Parallel data width (2-8,10,14)
		.DYN_CLKDIV_INV_EN("FALSE"), 
		.DYN_CLK_INV_EN("FALSE"), 

		.INIT_Q1(1'b0),
		.INIT_Q2(1'b0),
		.INIT_Q3(1'b0),
		.INIT_Q4(1'b0),
		
		.NUM_CE(1),
		.OFB_USED("FALSE"),
		
		.SRVAL_Q1(1'b0),
		.SRVAL_Q2(1'b0),
		.SRVAL_Q3(1'b0),
		.SRVAL_Q4(1'b0)
	)
	ISERDESE2_inst (
		.RST(r_iserds_rst),
		
		.D(i_clk_dclk),   
		.DDLY(w_dclk_delay),
		.O(w_clk_out), 
		
		.CLK(o_clk_hs),
		.CLKB(1'b0),
		.CLKDIV(o_clk_div),
		.CLKDIVP(1'b0),
		.DYNCLKDIVSEL(1'b0),
		.DYNCLKSEL(1'b0),

		.OCLK(1'b0), 
		.OCLKB(1'b0),
		.OFB(1'b0),
		.CE1(1'b1),
		.CE2(1'b0),
		
		.BITSLIP(1'b0), 
		.Q1(sample_value[0]),
		.Q2(sample_value[1]),
		.Q3(sample_value[2]),
		.Q4(sample_value[3]),
		.Q5(sample_value[4]),
		.Q6(sample_value[5]),
		.Q7(sample_value[6]),
		.Q8(sample_value[7]),
		
		.SHIFTOUT1(),
		.SHIFTOUT2(),
		.SHIFTIN1(1'b0),
		.SHIFTIN2(1'b0)
	);




endmodule

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

皮带,传送带异物检测识别数据集,2345张图像,yolo,coco,voc标记三种格式的数据集整理

皮带&#xff0c;传送带异物检测识别数据集,2345张图像&#xff0c;yolo&#xff0c;coco&#xff0c;voc标记三种格式的数据集整理 数据集分割 训练组79&#xff05; 1860图片 有效集14% 318图片 测试集7% 167图片 预处理 自动定向&#xff1a; 已应用 调…

sdk环境变量配置后不生效

sdk环境变量配置后 使用adb命令任显示 adb不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 解决方法&#xff1a;在环境变量的Path中添加platform-tools的地址

JavaEE 【知识改变命运】05 多线程(4)

文章目录 单例模式什么是单例模式饿汉模式懒汉模式多线程- 懒汉模式分析多线程问题第一种添加sychronized的方式第二种添加sychronized的方式改进第二种添加sychronized的方式&#xff08;DCL检查锁&#xff09; 阻塞队列什么是阻塞队列什么是消费生产者模型标准库中的阻塞队列…

RPC设计--从reactor设计 (IOthread)

主从reactor架构 一般的一个网络IO库都是主从reactor模式&#xff0c;即主线程中有一个MainReactor&#xff0c;其负责监听ListenFd&#xff0c;当接受到新的用户连接时&#xff0c;返回的clientfd并不会加入的MainReacotr&#xff0c;而是在子线程&#xff08;这里称为IO线程&…

STM32 出租车计价器系统设计(一) 江科大源码改写

STM32 出租车计价器系统设计 功能目标 驱动步进电机模拟车轮旋转&#xff0c;并实现调速功能。 设置车轮周长和单价&#xff0c;检测车轮转速和运转时间。 计算并显示行驶里程和价格。 硬件材料 28BYJ48 五线四相步进电机和 ULN2003 驱动板模块 测速传感器模块 嵌入式小系统…

威胁驱动的网络安全方法论

摘要 目前的网络安全风险管理实践很大程度上是由合规性要求驱动的&#xff0c;这使得公司/组织不得不在安全控制和漏洞上投入人力/物力。&#xff08;风险管理涉及多个方面&#xff0c;包括资产、威胁、漏洞和控制&#xff0c;并根据事故发生的可能性及造成的影响进行评估。威胁…

AUTOSAR:SOME/IP 概念

文章目录 1. 用例与需求1.1 典型用例1.2 对中间件的要求 2. 协议栈示例3. SOME/IP 概念3.1 中间件整体功能与架构3.2 服务组成元素详细解释 4. 服务发现机制深入剖析5. 总结 1. 用例与需求 1.1 典型用例 信息娱乐系统&#xff1a; 后座娱乐系统连接&#xff1a;允许后排乘客连…

如何将自己的PHP类库发布到composer仓库

将自己的 PHP 类库发布到 Composer 仓库&#xff0c;需要经过一系列的准备和操作步骤&#xff0c;以下是详细说明&#xff1a; 准备工作 创建类库项目&#xff1a;确保你的 PHP 类库项目具有清晰的目录结构&#xff0c;遵循 PSR-4 等 PHP 编码规范。通常&#xff0c;类文件应…

Formality:set_svf命令

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 svf文件的全称是Setup Verification for Formality&#xff0c;即Design Compiler提供给Formality的设置验证文件&#xff0c;它的作用是为Formality的指导模式(Gui…

线性dp—acwing

题目&#xff1a;数字三角形 898. 数字三角形 - AcWing题库 看某个点&#xff0c;是从那些路径过来的去分析 分析1&#xff1a; 代码1&#xff1a;&#xff08;顺序正推&#xff0c;二维dp数组&#xff09; #include<bits/stdc.h> using namespace std;const int N 5…

Selenium WebDriver:自动化网页交互的利器

Selenium WebDriver&#xff1a;自动化网页交互的利器 在当今快速发展的Web开发领域&#xff0c;自动化测试已经成为确保应用程序质量和用户体验的重要手段。Selenium WebDriver&#xff0c;作为Selenium工具包中的核心组件&#xff0c;正是这一领域的佼佼者。本文将详细介绍S…

对于相同问题大模型的生成为什么会不同?

AI因你而升温&#xff0c;记得加个星标哦&#xff01; 大模型的输出是一个token一个token的进行逐步输出&#xff0c;在输出策略上可分为两大类&#xff1a; 贪心解码&#xff1a;直接选择概率最高的单词。这种方法简单高效&#xff0c;但是可能会导致生成的文本过于单调和重复…

12.11作业

1.脑图 定义一个数组&#xff0c;用来存放从终端输入的5个学生的信息【学生的信息包含学生的姓名、年纪、性别、成绩】 1>封装函数 录入5个学生信息 2>封装函数 显示学生信息 3>封装函数 删除第几个学生信息&#xff0c;删除后调用显示学生信息函数 显示 4> 封…

C++11 常用-新特性

一、原始字面量——原文链接 原始字面量 R可以直接得到其原始意义的字符串&#xff08;用于简化&#xff1a;win路径转换、字符串换行需要加连接符&#xff09; 定义方式 //R “xxx(原始字符串)xxx”//这种情况原本在 win下是需要使用\\的 string str2 R"(D:\hello\worl…

独家首发 | 基于 2D-SwinTransformer + BiGRU-GlobalAttention的并行故障诊断模型

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 基于FFT CNN - BiGRU-Attention 时域、频域特征注意力融合的轴承故障识别模型-CSDN博客 基于FFT CNN - Transformer 时域、频域特征融合的轴承故障识别模型-CSDN博客 P…

ESP32-C3 入门笔记07: ESP-NOW动态绑定MAC地址. (ESP-IDF + VSCode)

ESP-NOW 简介 ESP-NOW [gitbuh] ESP-NOW 是一种由乐鑫公司定义的无连接 Wi-Fi 通信协议。在 ESP-NOW 中&#xff0c;应用程序数据被封装在各个供应商的动作帧中&#xff0c;然后在无连接的情况下&#xff0c;从一个 Wi-Fi 设备传输到另一个 Wi-Fi 设备。 CTR 与 CBC-MAC 协…

《Java核心技术I》并行数组算法

并行数组算法 Arrays类提供了大量并行化操作。 Arrays.parallelSort方法可以对一个基本类型值或对象的数组排序。 package arrays;import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import …

智创 AI 新视界 -- AI 助力金融风险管理的新策略(16 - 10)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

ASP.NET |日常开发中连接Oracle数据库详解

ASP.NET &#xff5c;日常开发中连接Oracle数据库详解 前言一、安装和配置 Oracle 数据访问组件1.1 安装ODP.NET&#xff08;Oracle Data Provider for.NET&#xff09;&#xff1a;1.2 引用相关程序集&#xff1a; 二、配置连接字符串2.1 连接字符串的基本组成部分&#xff1a…

ChatGPT 4:解锁AI文案、绘画与视频创作新纪元

文章目录 AI文案&#xff1a;激发文字的魅力&#xff0c;重塑营销与传播AI绘画&#xff1a;解锁艺术的无限可能&#xff0c;激发创意灵感AI视频&#xff1a;重塑视频创作流程&#xff0c;提升制作效率GPTs&#xff1a;构建个性化AI应用&#xff0c;赋能各行各业《ChatGPT 4 应用…