目录
1、静态时序模拟
- 静态时序模拟是提取整个电路存在的所有时序路径,计算信号在这些路径上的传播延时,检查信号的建立和保持时间是否满足时序要求。
- 静态时序分析可以对芯片设计进行全面的时序验证和功能验证,验证每一条路径,发现时序的重大问题,比如建立时间和保持时间冲突,slow path以及过大的时钟偏移。
2、verilog设计时,综合为锁存器的原因
- if语句中缺少else结构,系统默认else的分支下寄存器q的值保持不变,即具有存储数据的功能,所以寄存器q会被综合成latch结构。
- 条件语句中有多条赋值语句,每个分支条件下赋值语句的不完整。这也会产生latch。
- case选项列表不全且没有加default 关键字,也会产生Latch。
- 组合逻辑中always@()块内敏感列表没有列全(有irst和rd两个),该触发的时候没有触发,那么相关寄存器还是会保存之前的输出结果,因而会生成锁存器。直接用always@(*) 即可消除 latch。
3、可综合/不可综合结构
- 所有综合工具都支持的结构: always,assign,begin,end,case,wire,tri, aupply0,supply1,reg,integer,default ,for,function,and,nand,or,nor, xor ,xnor,buf,not, bufif1 ,notif0,notif1,if,inout,input,instantitaion,module,nagedge,posedge,operators,output,parameter,generate
- 所有综合工具都不支持的结构 :time,defparam,$finish,fork,join ,initial,delays, UDP,wait
- 有些工具支持有些工具不支持的结构 :casex,casez, wand,triand,wor, trior,real ,disable,forever,arrays,memoriles ,repeat,task,while
4、建立可综合横型的原则
要保证Verilog HDL赋值语句的可综合性,在建模时应注意以下要点:
- (1)不使用初始化语句。
- (2)不使用带有延时的描述。
- (3)不使用循环次数不确定的循环语句,如forever.while等。
- (4)不使用用户自定义原语(UDP元件)。
- (5)尽量使用同步方式设计电路。
- (6)一般不采用调用门级元件来描述设计的方法,建议采用行为语句来完成设计。
- (7)用always过程块描述组合逻,应在敏感信号列表中列出所有的愉入信号。
- (8)所有的内部寄存器都应该能够被复位,在使用FPGA实现设计时,应尽量使用器件的全局复位端作为系统总的复位,
- (9)对时序逻辑描述和建模,应尽量使用非阻塞赋值方式。对组合逻辑描述和建模,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值。
- (10)不能在一个以上的always过程块中对同一个变量赋值。而对同一个赋值对象不能既使用阻塞式赋值,又使用非阻塞式赋值。
- (11)如果不打算把变量推导成锁存器,那么必须在if语句或case语句的所有条件分支中都对变量明确地赋值。
- (12)避免混合使用上升沿和下降沿触发的触发器。
- (13)同一个变量的赋值不能受多个时钟控制,也不能受两种不同的时钟条件(或者不同的时钟沿)控制。
- (14)避免在case语句的分支项中使用x值或z值。
5、运算优先级
6、流水线操作
- 流水线操作的目的是把一个大操作分解为若干小操作,因为每一步操作变小了,所以时间更短。频率更快。
- 分解为若干小操作,可以让小操作并行运行,提高整体处理的速度。
- 流水线在理各个阶段都需蚕增加寄存蠢保存中间计算状态,而且多条指令并行执行会导致功耗增加,硬件复杂度增加。
7、 二进制转换
8、频率
HZ就是频率,就是1秒几下。50mhz,就是1秒50*10^6Hz下,1下就是1/(50*10^6)秒,再乘以10^9就是多少ns了1下了,简而言之:1/50mhz再乘以10^9,或者x*50mH/10^9=1。50mhz对应20ns
9、case、casez、casex
10、verilog中输入输出类型
输入端口可以由wire/reg驱动,但输入端口只能是wire;输出端口可以使wire/reg类型,输出端口只能驱动wire。
12、FIFO深度计算
宏观地,从整个时间域上看,"写数据=读数据",这个条件必须要满足,如果这个大条件不满足的话,用FIFO是没有效果的。但是在发送方"突发"发送数据的时间T内,是很有可能写数据>读数据的,因此FIFO的深度要能够保证,在这段时间T内,如果接收方未能将发送方发送的数据接收完毕的话,剩下的数据都是可以存储在FIFO内部而且不会溢出的,那么在发送方停止发送数据的"空闲时隙"内,接收方可以从容地接收剩下来的数据。
既:“写数据=读数据+存在FIFO内的数据”。
前提背景:50MHz 每秒50M个,花费时间(s)=传输个数/频率 就是每个花费1/50M (s),传输1000个花费多少。 T=1000/50Ms。
- 写时钟频率w_clk;
- 读时钟频率r_clk;
- 读时钟周期里,每Y个时钟周期会有X个数据读出FIFO。
- 写时钟周期里,每B个时钟周期会有A个数据写入FIFO,(应该是算上空闲周期了,比如发800个休息200个, 每1000个周期,有800个写入,这样每个周期有4/5个数据写入FIFO,在下面计算背对背时,肯定要算连续写入最高效率w_clk(最坏情况),然后读是按最慢的读出效率r_clk*X/Y,这样就是最坏的可能了,算出来是最大的FIFO深度);
1、题目里面并没有约束Burst突发的场景,在正常情况下,应该是这样的
空闲---Burst突发---空闲---Burst突发---空闲---Burst突发。
2、但是我们在计算中,需要考虑最极端的情况,
空闲---Burst突发---Burst突发---空闲---Burst突发---空闲。
即传输过程中,可能会出现"背靠背"的情况,那么我们设计的FIFO深度必须能够保正,在"背靠背"的时间段内,如果接收方没法接受所有数据,那么剩余的数据可以被存储在FIFO内部且不会溢出。那么就可以开始计算了。
假设"背靠背"时发送的数据 = BL,那么"背靠背"的时间 = BL / w_clk ,注意,这段时间内 写入频率 w_clk 。(每100个周期会写80个数据进来,背对背就是连续发送160)
- 发送方写入BL个要多少时间=BL/w_clk
- 接收方可以接受的数据 = (BL / w_clk) * (X/Y)*r_clk ,剩下的数据量放到FIFO内 = BL - ( BL / w_clk ) * (X/Y)*r_clk
depth = BL - BL * (X/Y) * (r_clk/w_clk)
13、牛客网部分知识点
1、锁存器对电平敏感的储存单元,不是同步时钟控制,会让设计的时序产生问题;
2、触发器是边沿敏感的储存单元;
3、寄存器是多个触发器构成:由于触发器内有记忆功能,因此利用触发器可以方便地构成寄存器,一个触发器能够存储一位二进制码;
4、Latch产生原因:if语句缺少else、条件语句不完整、case选项没有default、always@()块中敏感列表没有列全,always@(*);
5、从一个越界的地址中读取数据,那么System Verilog将返回数组元素类型的缺省值。四状态类型,例如logic,返回的是X,双状态类型例如int或bit,则返回0。这适用于所有的数组类型,包括定宽数组、动态数组、关联数组和队列,也同时适用于地址中含有X或者Z的情况。线网在没有驱动的时候输出是Z;
6、d = {<<4{8'b0011_0101}}; 表示把0011_0101分成宽度为4的两段,即0011和0101,再从右到左赋值给d,则d的值为 0101_0011,实现半字节倒序;
7、队列是一个大小可变, 具有相同数据类型成员的有序集合,一个队列只能有一个数据类型;
8、input、inout 类型不能声明为 reg 数据类型,因为 reg 类型是用于保存数值的,而输入端口只能反映与其相连的外部信号的变化,不能保存这些信号的值;
9、用always过程块描述组合逻辑,应在敏感信号列表中列出所有的输入信号;
10、$display命令的执行是安排在活动事件队列中,但排在非阻赋值赋值数据更新事件之前;
$strobe命令的执行是排在非阻塞赋值数据更新事件之后;
$display适合用来显示阻塞语句的赋值;
$strobe适合用来显示非阻塞语句的赋值。
11、随机数$random% (-b+1,b-1) 随机正数{$random}% (0,b-1);
12、接口信号必须使用非阻塞赋值来驱动;
13、case后不用加begin,每一个分支后加begin;
14、输出是reg型则不用管,输出是wire型,需要设置reg型变量stim_reg 然后assign stim=stim_reg;
15、always 后面加begin;
16、wire类型设计时表示导线结构,它不存储状态,只能负责传递驱动级的输出。assign驱动;
17、reg类型设计用于表示存储结构,它内部存储状态,并在时钟沿到来或异步信号改变等条件触发时改变内部状态。定义在always、initial、task或function代码块中;
18、logic类型是在reg类型基础上进行改进,使得它除了作为一个寄存器变量外,还可以被连续赋值、门单元和模块所驱动。任何使用wire线网类型的地方都可以使用logic,但是logic类型不能有多个结构性的驱动。多驱动时,如inout类型端口,使用wire;
20、声明是告诉编译器变量和类型,而不分配内存,一个变量可以在多处声明,但只能在一处定义。