520 likes | 668 Views
可编程 ASIC. 模块化硬件与进程模型. 目的. 第三部分(模块化硬件与进程模型)与第四部分(信号传输模型)均是讲述 vhdl 硬件描述语言的原理 这两部分的学习目的是为了让大家了解硬件描述语言的运行机制,了解硬件仿真的原理,有利于在以后的设计中使用多语言进行各种级别的建模; 对于打算从事 EDA 工具软件设计的学员也有一定的参考价值。. 数字电路的信号跳变特点. din0. 数字电路. dout. din1. din0. din1. dout.
E N D
可编程ASIC 模块化硬件与进程模型 电子科技大学
目的 • 第三部分(模块化硬件与进程模型)与第四部分(信号传输模型)均是讲述vhdl硬件描述语言的原理 • 这两部分的学习目的是为了让大家了解硬件描述语言的运行机制,了解硬件仿真的原理,有利于在以后的设计中使用多语言进行各种级别的建模; • 对于打算从事EDA工具软件设计的学员也有一定的参考价值。 电子科技大学
数字电路的信号跳变特点 din0 数字电路 dout din1 din0 din1 dout 输出(dout)的值只有在输入(din0,din1)发生变化的时候才会变化(可能有所延迟)理想情况下是瞬间变化,没有过渡时间。
数字电路的信号跳变特点 din0 数字电路 dout din1 din0 din1 dout 输出(dout)的值只有在输入(din0,din1)发生变化的时候才会变化(可能有所延迟)理想情况下是瞬间变化,没有过渡时间。
本节假设 • 为了问题分析的方便,本节暂时假设,输出的跳变与输入的跳变之间无延迟,跳变无过渡。 电子科技大学
用软件方法来仿真硬件行为 din0 数字电路元件 dout din1 din0 din1 dout 问题:如何用软件的方法来仿真这个硬件元件的行为?
用软件方法来仿真硬件行为 din0 数字电路元件 dout din1 Funct() { if(din0 和 din1满足某种条件) { dout = ‘0’; } Else { dout = ‘1’; } } // 在这里假设din0,din1和dout为全局量 din0 din1 dout
用软件方法来仿真硬件行为 din0 数字电路元件 dout din1 Funct() { if(din0 和 din1满足某种条件) { dout = ‘0’; } Else { dout = ‘1’; } } // 在这里假设din0,din1和dout为全局量 din0 din1 dout 问题:何时调用Funct?
时间方案(调用方案)1 din0 数字电路元件 dout din1 t din0 din1 dout • 按照特定的分辨率对时间轴作细划分,调用funct。 • 继承了传统电子系统(模拟,平滑系统)的仿真思想。 • 缺点:调用频繁,仿真时cpu负担过重。
时间方案(调用方案)2 din0 数字电路元件 dout din1 t din0 din1 dout • (理想数字系统仿真)只需要对输入跳变点调用Funct。 • 缺点:只适合于理想数字波形。
ASIC仿真时间方案 • 基本上是采用第二种方案。 • 以下的仿真讨论均使用第二种方案。 电子科技大学
波形记录举例 din0 数字电路 dout din1 t0 t t1 t2 din0 din1 dout
st为仿真时间指针 仿真算法流程 St指向波形文件中 的起始时间点 读取波形文件中时间st时 的输入值(din0, din1…) 调用Funct 往波形文件记录St时的 输出值(dout, …) St指向波形文件中 的下一个时间点 N Y 时间t结束? 退出 电子科技大学
考虑复杂的情况:多元件(多模块) a e u1 b u3 g c u2 f U1: process(a, b)… U2: process(c)… U3: process(e, f)… VHDL解决方案:一个硬件模块对应一个软件进程。 电子科技大学
进程调度(方案1) a e u1 b u3 g c u2 f 方案1: 偷懒方法。 当任何一个输入(a,b,c)发生变化时,均将所有的进程 调度一次。 • 问题:用什么来决定调度的顺序? 方案1修补:根据信号流向来确定调度顺序。 • 问题:当存在信号反馈的时候又如何处理? 电子科技大学
进程调度(方案2) a e u1 b u3 g c u2 f 方案2: 对每一个模块,只有当该模块的输入发生变化时,该 模块才被调用。 • 问题:当模块的输入发生变化,但是又没有引起模块的硬件动作时,这种方法会有什么缺点? • 例子:寄存器的时钟发生变化时,寄存器才会产生硬件动作,而数据输入发生变化时,寄存器并不产生任何动作。 电子科技大学
VHDL中process的定义 • ModuleName:Process( 敏感信号列表 ) • Begin • -- 进程描述语句。 • End process; 当敏感信号列表中的任何一个信号发生变化,该进程都会被调度 电子科技大学
Process例子 • 假设U2为非门,则例子程序如下: • U2: process( c ) • Begin • if( c = ‘1’ ) then • f <= ‘0’; • else • f <= ‘1’; • end if; • End process; 当c发生变化时,该进程被调度. 表示信号赋值。 电子科技大学
VHDL的进程调度 a e u1 b u3 g c u2 f a b c e f 电子科技大学
a e u1 b u3 g c u2 f VHDL的进程调度 a b 进入一个新的 仿真周期 c 一个 子仿真周期 e f U1_process 被调度的进程: 电子科技大学
VHDL的进程调度 a e u1 b u3 g c u2 f a b c 子仿真周期1 e f 子仿真周期2 进入一个新的 仿真周期 U1_process 被调度的进程: U3_process 电子科技大学
子仿真周期1 子仿真周期2 VHDL的进程调度 a e u1 b u3 g c u2 f a b 进入一个新的仿真周期 c e f U1_process 被调度的进程: U2_process U3_process
联想:SARS隔离检测 隔离 子周期1 隔离 子周期2 隔离 子周期3 电子科技大学
VHDL进程调度算法 • 1.如果仿真事件(有信号发生变化)搜索完,则结束仿真;否则,跳到下一个信号事件点,此时进入一个新的仿真周期; • 2.找出所有对发生变化的信号敏感的进程,进入一个新的子仿真周期,依次对这些进程调度一次; • 3.如果进程调度后出现新的事件,则回到第2步;否则回到第1步。 电子科技大学
VHDL仿真思想 • 子仿真周期的时间就是一个Delta延时,而Delta延时为0延时。 • 显然,一个仿真周期可以包含多个子仿真周期,也就是包含多个Delta延时。 • Delta延时数目的增加,并不会推进仿真时钟。也即“微观时间增量不改变宏观时间”;只有仿真周期的增加才会推进仿真时钟。 • 硬件模块的运行之间是并行的关系;软件进程的调度之间是并发的关系。硬件的并行是通过软件的并发来仿真。 电子科技大学
补充:并发与并行 • 并发: 电子科技大学
补充:并发与并行 • 并行就是真正的同时,在任何时刻(瞬间),多个进程都在同时地运行。 电子科技大学
VHDL软件体系 VHDL 源代码 process(…); process(…); process(…); …… 编译 器 进程调度器 (仿真器) 仿真结果 逻辑综合器 EDA工具 综合形成的源码形式网表 硬件电路 电子科技大学
进程结构体(即vhdl源代码)里已经描述了整个硬件的形态,所以它可以被综合器综合成硬件;进程结构体(即vhdl源代码)里已经描述了整个硬件的形态,所以它可以被综合器综合成硬件; • 并不是所有描述方式的vhdl代码都可以被综合成硬件。太抽象的描述只适合做系统建模和仿真。 电子科技大学
显然综合器是不会去关心敏感信号量的,因为它不存在进程调度的问题,而是直接根据进程体内的代码来形成硬件电路。显然综合器是不会去关心敏感信号量的,因为它不存在进程调度的问题,而是直接根据进程体内的代码来形成硬件电路。 电子科技大学
但是要注意,即使编写的是面向综合的代码,敏感信号量仍然需要补全。因为敏感信号的缺漏对于仿真器来说是一个错误,会导致仿真时应该被调度的进程没有得到调度。但是要注意,即使编写的是面向综合的代码,敏感信号量仍然需要补全。因为敏感信号的缺漏对于仿真器来说是一个错误,会导致仿真时应该被调度的进程没有得到调度。 • 而综合器形成的综合后仿真用的网表源文件,是保证不丢失敏感信号的。 • 如果设计者丢失了敏感信号,就会造成设计级别的代码和综合后的代码之间仿真结果不相符。 电子科技大学
对于敏感信号 • 一个模块,并非所有的输入都必须作为敏感信号,只有引起硬件动作的信号才必须作为敏感信号。 电子科技大学
对于敏感信号 • 将所有的输入信号放入进程的敏感信号表中,在逻辑上并没有什么错误,但是会引起进程调度频繁而导致仿真效率降低(cpu负担太重)。 电子科技大学
事情结束了吗? 用另外的方式建立敏感信号表,这里省略。 b c a U1 U2 假设u1和u2都是“直连逻辑”(在数字逻辑设计中,叫做 缓冲器元件),则它们的进程描述(用c语言)如为: /*敏感信号量 为(a) */ Void functU1() { b = a; } /* 敏感信号量 为(b) */ Void functU2() { c = b; } 很显然,当a 的值发生变化 时,会激活两 个仿真子周期, functU1和functU2 依次得到调度, 从而a的值得能够 可靠地传播到c。
事情结束了吗? b c a U1 U2 假设u1和u2都是“直连逻辑”(在数字逻辑设计中,叫做 缓冲器元件),则它们的进程描述(用VHDL语言)如为: Process(a) Begin b <= a; End process; 很显然,当a 的值发生变化 时,会激活两 个仿真子周期, functU1和functU2 依次得到调度, 从而a的值得能够 可靠地传播到c。 Process(b) Begin c <= b; End process;
尝试加上时钟变成时序电路 b c a U1 U2 注意这两个进程 的敏感信号量都 是clk。 clk C语言描述的进程如下: Void functU1() { if(rising_edge(clk)) b = a; } Void functU2() { if(rising_edge(clk)) c = b; }
尝试加上时钟变成时序电路 b c a U1 U2 当clk发生变化时,这两个 进程会被激活,并且依次 在一个子仿真周期内被调 度。 clk C语言描述的进程如下: Void functU1() { if(rising_edge(clk)) b = a; } Void functU2() { if(rising_edge(clk)) c = b; }
尝试加上时钟变成时序电路 b c a U1 U2 如果首先调度functU2,再 调度functU1 ,则仿真结 果能够符合实际的硬件行 为。 clk C语言描述的进程如下: Void functU1() { if(rising_edge(clk)) b = a; } Void functU2() { if(rising_edge(clk)) c = b; }
尝试加上时钟变成时序电路 b c a U1 U2 而如果首先调度functU1, 再调度functU2,则仿真 结果与实际的硬件行为 不符! clk C语言描述的进程如下: Void functU1() { if(rising_edge(clk)) b = a; } Void functU2() { if(rising_edge(clk)) c = b; }
问题 • 我们发现,调度顺序的不同,会导致截然不同的仿真结果; • 以下是这个问题的另外一种形式的表述…… 电子科技大学
将u1和u2合并成新的元件u3,并且只用一个进程函数描述将u1和u2合并成新的元件u3,并且只用一个进程函数描述 元件合并 b c a U3 U1 U2 方式1: 方式2: /* 敏感信号量 为(a, b)*/ functU3() { b = a; c = b; } /* 敏感信号量 为(a, b) */ functU3() { c = b; b = a; } 显然,两种 方式中,a的 值都能够可 靠地传输到c。 电子科技大学
值得注意的是,这种纯组合电路的进程函数中,被读的信号应该都加入敏感信号表中值得注意的是,这种纯组合电路的进程函数中,被读的信号应该都加入敏感信号表中 将u1和u2合并成新的元件u3,并且只用一个进程函数描述 b c a U3 U1 U2 /* 敏感信号量 为(a, b)*/ functU3() { b = a; c = b; } /* 敏感信号量 为(a, b) */ functU3() { c = b; b = a; } 显然,两种 方式中,a的 值都能够可 靠地传输到c。 电子科技大学
值得注意的是,这种纯组合电路的进程函数中,被读的信号应该都加入敏感信号表中值得注意的是,这种纯组合电路的进程函数中,被读的信号应该都加入敏感信号表中 将u1和u2合并成新的元件u3,并且只用一个进程函数描述 b c a U3 U1 U2 /* 敏感信号量 为(a, b)*/ Process(a,b) begin b <= a; c <= b; End process; /* 敏感信号量 为(a, b) */ Process( a,b) begin c <= b; b <= a; End process; 显然,两种 方式中,a的 值都能够可 靠地传输到c。 电子科技大学
这样在a发生变化时,导致进程被调度两次,从而保证了a的值顺利地在一个仿真周期内“立即”地传输到c。这样在a发生变化时,导致进程被调度两次,从而保证了a的值顺利地在一个仿真周期内“立即”地传输到c。 将u1和u2合并成新的元件u3,并且只用一个进程函数描述 b c a U3 U1 U2 /* 敏感信号量 为(a, b)*/ Process(a,b) begin b <= a; c <= b; End process; /* 敏感信号量 为(a, b) */ Process( a,b) begin c <= b; b <= a; End process; 显然,两种 方式中,a的 值都能够可 靠地传输到c。 电子科技大学
给这个系统加上时钟,变成时序电路…… b c a U1 U2 clk /* 敏感信号为(clk) */ FunctU3() { if( rising_edge(clk) ) { c = b; b = a; } } 此时仿真没问题 电子科技大学
b c a U1 U2 clk /* 敏感信号为(clk) */ FunctU3() { if( rising_edge(clk) ) { b = a; c = b; } } 此时仿真出错,与实际不符! 交换顺序! 电子科技大学
这是为什么?如何解决? 电子科技大学
作业(挑战免考题的基础) • 以下是一个数字硬件系统的模块框图。 a u1 b u3 d u2 c 电子科技大学
要求 • 1. 为输入输出信号定义一种波形记录文件格式,编写函数,能够根据文件自动画出信号波形; • 2. 编写rising_edge函数: bool rising_edge(std_logic clk ); 其中std_logic为自定义类型,其在数字逻辑上的值暂时为(‘0’, ‘1’)。
要求 • 3. 假设已经有工程师利用c语言编写了这三个模块的设计函数(进程函数): void FunctU1(); void FunctU1(); void FunctU3(); 请你在上述基础下,编写完整的仿真程序或函数(要求c语言),对这些进程函数进行合理地调度,正确地对这个硬件系统进行仿真,并自动画出整个仿真的输入输出波形。 • 4. 自己维护好设计文档。