网志

VHDL教程-一个实际示例-第3部分-VHDL测试平台

吉恩·布雷尼曼2011年6月25日8条评论

In part 1 在本系列文章中,我们集中于硬件设计,包括CPLD部件的I / O特性的一些VHDL定义。  在 part 2,我们描述了 此设计的CPLD的VHDL逻辑。 在第3部分中,我们将展示整个VHDL设计和相关的测试,这些测试用来证明我们实际上已经设计了我们刚开始设计的东西。

快速链接

首先,让我们将现有设计的所有部分放到一个清单中。 这使我们对设计有了一个很好的了解,并帮助我们设计了一个测试策略。 这是我们的数据采集引擎的整体设计:

本文以PDF格式提供,便于打印

根据上面的代码,Xilinx ISE环境使构建测试平台代码的基本框架变得简单。要开始此过程,请从“项目”下的菜单项中选择“新源”。这将启动“新源向导”。在向导中,选择“ VHDL测试台”,然后输入新模块的名称(单击“下一步”继续)。然后,“新源向导”允许您选择要与新源关联的源(在这种情况下,是上述VHDL代码中的“ acpeng”),然后单击“下一步”。然后,向导为测试平台模块创建必要的框架(请参见下文)。

上面的框架包含我们测试平台所需的许多代码。 它包括一个组件声明部分(第19-38行),输入信号声明和初始化(第41-48行),输出声明(第50-59行)和测试组件实例化(第67-85行)。  该框架还包含两个时钟的固定过程(Mclk-第87-94行和Sclk-96-102行,以及时钟速率的定义-62-63行)以及激励过程的存根版本(stim_proc:process-第105-118行),这将用于创建必要的激励声明以彻底测试我们的设计。

该框架为我们提供了一个良好的起点,从此起点可以构建完整的测试平台。 我喜欢从基础开始我的测试台设计,然后扩展激励的产生,直到我们充分行使了设计经验。 我的第一步通常专注于时钟生成。 为此,我们将需要调整一些常数以匹配我们的目标时钟速率,以及一些小的变化,以便我们可以将SPI时钟(Sclk)抑制到从SPI设备发送或接收数据的时间。

 

这很简单。以上语句将主时钟(Mclk)和SPI时钟(Sclk)更改为其各自的速率(8 MHz和10 MHz)。现在我们需要对SPI时钟生成逻辑进行一些修改。 首先,我们需要创建两个信号来辅助门逻辑。 第一个信号Sclk_inh用于启用和禁用时钟信号。 第二个信号Sclk_raw是替换时钟信号。 我们将使用Sclk_raw生成门控时钟信号,该信号将分配给我们的UUT(被测单元)的Sclk输入。

定义了新信号后,我们现在可以在Sclk_process中修改逻辑。 在此过程中,我们将使用Sclk_raw构建一个连续的时钟信号,该信号在Sclk_period的每个二分之一之间切换,从而产生一个自由运行的10 MHz时钟。 在此时钟生成序列的旁边,我们通过将Sclk_raw信号与Sclk_inh信号进行“与”运算来创建Sclk输入。 这样,每当Sclk_inh设置为'1'时,Slkk将以10 MHz进行切换,否则它将保持在'0'。我们将在stim_proc进程中使用Sclk_inh信号将SPI数据输入和输出设备。

现在,我们需要创建一个过程来为我们的设计生成模拟ADC数据。为此,我们需要一个 一个计数器来跟踪要从我们的ADC模拟发送的数据(ADCcount)。 接下来,我们需要创建一个过程来处理ADC_Data行的生成。 在此过程中,我们等待ADC_LRCK的上升沿(ADC左/右时钟-线109)。 我们使用该上升沿将ADCcount信号初始化为ADC数据生成序列的倒计时值(第110行二进制中的32或“ 10000”),并将ADC_Data初始化为“ 1”(第111行)。 然后,我们等待ADC_LRCK信号的下降沿(线112)。从那里我们进入一个循环,在该循环中我们将为模拟(ADC数据线114)生成ADC_Data数据线的简单切换。 设置了ADC_Data信号后,我们等待ADC_BCK的下降沿将我们带入下一个循环(第115行)。在第116行,我们递减ADCcount值,然后在第113行进行测试,以确定何时我们生成了足够的数据来模拟ADC对ADC_LRCK和ADC_BCK信号排序的响应(您可以参考 用于DSP格式和nvSRAM写入的I2S / SPI时序 本文第2部分的图表,以查看所需的ADC序列).

好的,现在我们需要将所有组件连接在一起,并开始使事情发生,但是首先,让我们制定一个如何测试设备的计划。 我喜欢以复位脉冲(从高到低,然后返回高)和短暂的延迟(让我们有机会看到我们的主状态机-Eng_State保持空闲状态直到发出命令)开始任何测试。 接下来,我们应该发送SPI命令来设置样本大小并开始收集序列。 其余的只是在等到收集突发运行为止。 这是验证设备基本功能所需的全部内容。 当然,我们可以添加其他测试以练习所有样本数量计数(从1到127),但是暂时就足够了。

 

因此,快速运行此过程,第124-157行替换了stim_proc进程的旧主体。 按照计划,我们有一个简短的复位和保持序列(第124-130行)和一个SPI命令序列,以将采样计数设置为1并设置“运行”标志(第132-157行)。

现在我们可以开始查看模拟数据。 运行仿真并捕获第一个2.5us,我们可以检查复位脉冲和SPI命令的影响。

Let's start 通过检查我们的两个自由运行的时钟信号(mclk和sclk_raw),看它们是否 已正确生成。 对于mclk,我们可以看到信号在前500ns内完成了4个周期,这给了我们500ns / 4或125ns的周期,给了我们8MHz的频率。 好,到目前为止,我们有权利。 对于sclk_raw,我们可以看到信号在前500 ns中完成了5个周期,这给了我们500ns / 5的周期(100ns),给了我们10 MHz的频率。  OK, two-for-two. 查看sclk信号(即sclk_raw和sclk_inh的逻辑与),可以看到在跟踪的前1000ns期间,sclk始终为低电平。 目前,这就是我们想要的。

现在,让我们看一下复位线如何影响设计。 在上面的跟踪中,复位信号在断言(低电平)时开始(100ns后释放),再断言100ns后重新置位,然后最终释放。 在前500ns内,所有迹线(mclk和sclk_raw除外)都没有变化。 这向我们展示了两件事,首先是复位没有真正的效果,上电状态和复位状态之间没有区别。 它还显示了adc_bck信号( seqcount的LSB,在复位期间保持低电平)。 释放复位并完成两个mclk周期后,adc_bck开始切换(以2MHz的速率)。

好的,现在要使事情进展,我们需要向设备发送一个SPI命令, 'RUN' bit set, 为了开始采集突发。 为此,我们需要选择器件(CS ='10')并提供适当的数据和时钟序列(注意:由于CS线设置为“ 10”,SDO线从三态转换为低电平,这是“运行”标志的当前状态)。因此,在1.1us(释放复位线后800ns,即测试台的130-132行)处选择了该设备。然后100ns之后,SPI数据线(sdi)设置为高电平。 这将是SPI命令的MSB或我们的RUN位。 50ns后,sclk_inh信号升高到“ 1”,从而能够生成Sclk脉冲(从1.3到2.05us的8个脉冲)。从这里开始,测试平台将使用sclk的边缘,因此我们可以同步 SPI数据线更改为sclk。 Sclk信号先变高然后变低(第137-138行)之后,我们清除SDI信号,准备向SPI外设锁存器(CycleCnt的高位)发送六个零。然后,测试台等待六个Sclk周期(第140-151行,锁存在CycleCnt的高位)。 在六个Sclk周期后,SDI被驱动为1,以设置CycleCnt寄存器的低位。现在,我们再等待一个Sclk脉冲,然后清除sclk_inh行(第153-155行),切断Sclk脉冲的产生。为了完成SPI写序列,我们等待250ns,然后将CS线重新置为'no select'状态或'11'(156-157 @ 2.3行)。 us).

查看到目前为止的痕迹,需要注意以下几点: 1)Sclk线上的时钟脉冲通过器件传递到Eng_Sck线(这里没有问题,因为ADC_CS和nvSRAM_CS都保持高电平),2)SDI线上的所有数据都传递给Eng_So线。 这些都不是真正的问题。 在与设备内的SPI外围锁存器通信期间,VHDL代码可能抑制了Eng_Sck和Eng_So信号,但是这会增加设计的复杂性,并且可能会增加CPLD中的资源使用(拥有一个很少有备用资源,以备将来需要更改时使用)。 值得一提的另一件事是,在CS线上进入“不选择”状态之前,即2.25us,SDO线变高(就在它回到三态之前)。当器件处于内部SPI外设锁存状态(CS ='10')时,SDO线始终以“运行”标志状态驱动。 刚完成向零件发送“运行”命令后,我们看到了该命令的效果,这现在导致SDO线变高。 这向我们表明该设备实际上已经识别了我们的命令,并且正在准备开始数据采集周期。

此时,测试台代码处于“永远等待”阶段,等待设备完成采集序列。因此,让我们及时查看一下,看看设备是否正确完成了工作。现在,让我们进一步缩小范围,并检查将“标头”写入nvSRAM芯片。


 

“头”仅是我们的nvSRAM器件的突发模式写入序列的初始部分。 该序列是一个8位写入操作码('00000010'b),后跟一个右对齐的24位地址字段(7个零,然后是17位nvSRAM起始地址零)。检查上述迹线,从〜2.25us开始,我们看到nvSRAM_CS行进入选择状态('0')。 在其余的采集序列中都是这种情况。 nvSRAM_CS变低后不久,我们会看到Eng_Sck信号的32个脉冲,以及六个零,一个零和另外19个零的nvSRAM数据(在Eng_Sck的上升沿测得)。

现在,让我们看一下第一个ADC采样序列。这是选通ADC(ADC_LRCK),然后是一系列串行位时钟(ADC_BCK)的地方。

放大一下ADC信号(下图),我们可以看到ADC周期的开始。在ADC_BCK的下降沿,ADC_LRCK变为高电平,然后在下一个ADC_BCK的下降沿返回低电平。 此时,Eng_So线上存在ADC数据的第一位(左通道的MSB)(在这种情况下为'0')。为了将ADC数据位输入nvSRAM,它必须在Eng_Sck的上升沿保持稳定。到目前为止,一切似乎都进展顺利。在上图中,我们可以看到“ 1”和“ 0”的切换模式(由测试台的ADCcmp过程内部的第113-117行生成)。 Eng_So和ADC_data线上总共有32位(16-'0'/'1'序列),以及32个Eng_Sck时钟周期(将两个ADC值写入四个字节写入nvSRAM)。 ADC_BCK继续通过ADC帧提供时钟,如ADC部件的规格书中所述。

经过验证的ADC周期后,我们再次缩小并查看完整的激光二极管周期(如下所示)。 LaserHiLow信号的整个周期内有16个ADC周期(计算ADC_LRCK脉冲)。

经过验证的激光二极管周期后,我们再次缩小并查看完整的采集周期(如下所示)。在整个采集周期内,共有32个激光二极管周期(计算LaserHiLow脉冲)。在数据采集周期结束时,我们可以看到Int(中断)信号的短高脉冲,它通知μProcessor请求的周期已完成。

这就差不多完成了验证阶段。 看起来一切正常。 好吧,我之前研究的过程中出现了一些小故障。 在nvSRAM标头测试中,我注意到Eng_SO线上的高电平脉冲位置存在一个小错误。 模拟迹线已得到纠正,但是现在我需要纠正设备的VHDL源。 所以这是更改:

 

顶部的180-184行已替换为底部的180-183行。 更改的效果是将nvSRAM报头序列中的“ 1”移回了一点时间。 在较高的序列中,ENG_SO线从seqcount“ 001011”到“ 001100”为高。 在较低的顺序中,ENG_SO线从“ 001100”到“ 001101”为高。 较低序列的编码更简单,因为我们可以忽略seqcount的LSB,并触发对位4到1(忽略位0)的更改。

ew,我认为我(最终)做到了。 在硬件设计,VHDL编码以及最后的测试阶段,我们已经有了一个想法或规范。 我再次向自己(并希望向您)证明了测试的重要性。 错误隐藏在那里,您所要做的就是找到并修复它们。

Until later,

Gene


吉恩·布雷尼曼(Gene Breniman)先前的文章:
   VHDL教程-一个实际示例-第2部分-VHDL编码
吉恩·布雷尼曼(Gene Breniman)的下一篇文章:
   深度嵌入式设计示例-逻辑替换

[-]
评论者 杜尼尔2012年5月18日
哦,很不错的教导是如何创建一个寄存器集并将其放入状态机,即使只有一个寄存器也是如此:“内部SPI外设命令集将由一个寄存器组成,其中包含运行标志和运行长度变量。 ”在第2部分中,我指出大学的教程没有在入门课程中讲授这一点-它是实际设计不可或缺的
[-]
评论者 杜尼尔2012年5月18日
基因:出色的教学,pby是我所学的最好的,甚至超出了大学课程的材料。我是Verilog IC测试工程人员,但必须为新项目使用VHDL。编译并模拟了您的介绍Clk_Div及其测试平台,需要进行一些调整才能编译。接下来,我将做这个ADC引擎,让您知道它是否按原样运行以及如何在ModelSim中运行
[-]
评论者 斯蒂芬布2020年1月20日

嗨,吉恩(Gene),您知道您现在的这篇文章的浏览量超过70,000吗?

这些年来,您已经帮助了很多人。


[-]
评论者 杜尼尔2012年5月18日
“编译并模拟了您的介绍Clk_Div及其测试平台”,我的意思是您之前的文章“ VHDL教程原定于2007年10月4日发布
[-]
评论者 杜尼尔2012年6月20日
吉,吉恩,你在那里吗?作为VHDL新手,我花了一个星期的苦心弄清楚要进行20多次调整才能在ModelSim上编译此代码-我一直坚持下去,因为设计很有趣,并且Xilinx模拟器上有一些波形,所以它一定对您有用以某种方式,形状或如果您想要更正,请让我知道,我将在这里发布。我们Veriloggers永远都不会在源代码中遇到这些麻烦
[-]
评论者 尤伯2017年12月21日

您好,您可以张贴更正的吗? 

[-]
评论者 索纳里402014年3月19日
嗨基因
我是该领域的新手,正在尝试为我的项目论文编写VHDL代码。我正在尝试为ARINC 429接口的SPI内核编写代码,必须在Model sim中进行仿真。请吉恩帮我。
我来自传感器领域,对VHDL中的编码了解不多。我已经学习了VHDL,但是在编写代码方面仍然不是很好。如果您能帮助我编写代码,我将非常感谢。提前致谢。
[-]
评论者 mikhail_soloviev十月13,2016

吉恩,我不能为您的努力而感激。分享超出学术范围的内容,可以真正了解如何将“裸”知识转化为有用的产品。非常感激!

要发布对评论的回复,请单击每个评论所附的“回复”按钮。要发布新评论(而不是回复评论),请查看评论顶部的“写评论”标签。

注册后,您可以参加所有相关网站上的论坛,并获得所有pdf下载的访问权限。

注册

我同意 使用条款隐私政策.

试试我们偶尔但很受欢迎的时事通讯。非常容易退订。
或登录