Verdi波形查看transaction+门控时钟+时钟切换+vcs的ucli+斐波那契LFSR和伽罗瓦LFSR

发布时间 2023-09-24 14:02:19作者: 大浪淘沙、

Verdi波形查看transaction

除了以下两个选项以外,

+UVM_TR_RECORD
+UVM_LOG_RECORD

还需要声明+UVM_VERDI_TRACE选项

+UVM_VERDI_TRACE=UVM_AWARE+RAL+TLM+MSG+HIER+PRINT

否则使用的是VC的环境抓取,而不是Verdi环境。(Verdi Transaction debug)
image

门控时钟

时钟门控如果仅仅使用一个与门操作,则在复位毛刺出现以后,导致时钟毛刺,导致时序错误。

为了解决复位毛刺,引入锁存器、寄存器的方案。不管引入何种方案,都会引入额外的竞争冒险。
因此需要额外考虑建立保持时间的满足。
image
image
https://zhuanlan.zhihu.com/p/139363948

寄存器相比锁存器,建立保持时间更容易满足,但是额外引入了一个单元增大了面积,加之锁存器往往采用cell工艺库实现,不存在skew问题,建立保持时间容易得到满足。因而广泛采用的是锁存器。

时钟门控也可以使用rtl直接编写,但是我觉得还是用库更安全。

时钟切换

时钟切换也有一套自己的逻辑。如果直接切换是不对的。如果有工艺库,我觉得还是用工艺库吧。
引入以下链接,其实写的并不清晰,重要信息和逻辑性缺乏,难以理解。
https://mp.weixin.qq.com/s/uGpon0hVjSiLSQV3zrFSjA
但是以下信息是明确的:
如果直接使用简单粗暴的代码进行时钟切换:

assign  outclock = select? clk1: clk0;

这种写法是肯定会产生毛刺的,这对整个芯片系统是很危险的,很容易进入亚稳态的情况,系统很容易bug。(本质上还是select的问题,select要是往后移动一些,在两个时钟都为高的情况下切换,就可以的)
image

所以设计时钟切换也有它的一套复杂逻辑。

vcs的ucli

ucli是vcs自有的一些库,用于在tcl环境下调用,也遵守tcl语法。典型的fsdbDumpVars等命令,从灵活性考虑,也使用ucli更为方便。

对于函数调用部分,有一些限制,但是也许有用。

在init的代码处调试

在以下代码直接执行后,static 的function F应该是自动执行了一次。

module mod1;
  class C;
     static int I=F();
     
     static function int F();
         logic log1;
         begin
             log1 = 1;
             $display("%m log1=%0b",log1);
             $display("In function F");
             F = 10;
         end
     endfunction
     
  endclass
endmodule

而使用ucli,可以添加断点,然后执行:
先进入init部分

./simv -ucli=init

进入后,先添加断点。C为函数类名,F为静态方法。

init%stop -in \C::F

然后执行一个0时间,则调到该类的静态方法处停止

init%run 0

再执行一个0时间,则执行了该静态方法,然后退出到ucli

init%run 0
ucli%

使用调用,仍可再次触发

ucli% \C::F

内部调用函数

对于以下代码,不使用-R选项编译和运行,而是单独分开,先编译。

program P1;

  integer i=1;
  
  class c;
     task prg_tsk_int(int n1 = 10);
     		$display("prg_tsk_int n1 = %0d",n1);
     endtask
     
     function int prg_func_int(int n2 = 12);
     		$display("prg_func_int n2 = %0d",n2);
     		return 1;
     endfunction
  endclass
  
  c c1=new();
  
  initial begin
   #2
   c1.prg_tsk_int(i);
   c1.prg_func_int(i);
  end
endprogram

运行的时候,使用以下:

simv -ucli

运行到initial里面

run 1

调用函数

call {c1.prg_tsk_int(100)}

根据以上:
通过使用call调用一些function修改class的值,然后再触发sequence,达到不同sequence的效果。

斐波那契LFSR和伽罗瓦LFSR

LFSR(线性反馈移位寄存器),它的作用是产生伪随机数。伪随机数的用处是可以在编码和解码的时候使用。
在PCIe的差分系统中,数据流中出现重复的序列后,导致较强的EMI干扰(电磁干扰,Electromagnetic Interference,EMI),进行扰码随机化后,EMI的噪声会减弱。(频谱被展宽)

PCIe 内部存在扰码器。扰码器需要初始值相同,才能在发送端和接收端通信。因此PCIe 设备使用COM字符,使得发送端和接收端都能识别,对初始值进行设定。
image
由于LFSR在每个周期都会进行更新,因此需要暂停的时候需要进行处理。在PCIe中,数据流添加了SKIP字符,该字符是不需要进行扰码和解扰处理的,因此这些字符出现时,LFSR将进入暂停状态。

多项式和生成序列

从视频中截取:
https://www.bilibili.com/video/BV1k94y1x7Bu/?spm_id_from=333.337.search-card.all.click&vd_source=0b160b3f23f010d84a4c31e761257ea4
线性移位寄存器,本质是寄存器,使用线性(异或操作)和移位,实现寄存器的随机性。
对生成序列产生影响的位置叫抽头。
在以下4级LFSR中,C4=C1=C0=1,右边的C1和C0做异或操作,移动到C4的位置。
image

在多项式右上角的标号,应该仅仅是一个标号,而不是一个次方的意义,只是表示哪些地方应该做异或操作,然后将异或结果移动到哪里。
image

斐波那契和伽瓦罗

● 斐波那契是多个触发器的输出通过异或逻辑,控制一个触发器的输入(多项式和生成序列中的例子)。
● 伽瓦罗是一个触发器的输出通过异或逻辑,控制多个触发器的串行输入。

伽罗瓦LFSR具有更高的速度,因为两个触发器之间只有一个异或门。斐波那契LFSR在首尾两个寄存器之间有多个异或门,组合逻辑延时更大,因为为了满足建立保持时间的要求,其频率更小(周期更大),速度更慢。

斐波那契

https://zhuanlan.zhihu.com/p/620450000
以三级LFSR,反馈函数为: image 为例

从左到右依次递减编号:
image
从左到右依次递增编号:
image

伽瓦罗

https://zhuanlan.zhihu.com/p/620450000
以三级LFSR,反馈函数为: image 为例:
从左到右依次递减编号:
image
从左到右依次递增编号:
image

CRC8 CCITT算法

伽瓦罗,多项式为X^8 +X^2+X+1
image

PCIe的扰码电路

image
工作波形:
image