FPGA/IC笔试——NVIDIA
Timing path 时序路径分析方法: ➢ 分析时序路径时常见的变量:
Tclk = 时钟周期,是可变的,比如1KHz ~ 5.0GHz T
cq = 触发器的时钟端C到输出端Q的延时,是器件属性,是固定不变的
Tcomb = 两个触发器之间组合电路的延时,是可变的,可以通过设计进行优化逻辑
Tsetup = 建立时间是触发器的固有属性,是定值
Thold = 保持时间是触发器的固有属性,是定值
Tskew = 相邻两个触发器之间的时钟的偏移,是可变的
◆ Setup time violation: ➢ 建立时间在静态时序分析时必须满足以下条件:
➢ Tclk > Tcq + Tcomb + Tsetup - Tskew
➢ 即:Tclk - Tcq - Tcomb + Tskew > Tsetup
➢ 如果setup time violation, 则上述公式不成立。
◆ Setup time violation solution:调整上述公式中的变量:Tclk, Tcomb,Tskew
➢ 增大Tclk(时钟周期):
就是降低数字系统的工作频率
➢ 减少Tcomb(组合逻辑时延):
从数字电路逻辑功能设计的角度看 » 在组合电路之间插入寄存器,增加流水线(pipeline); » 在不改变逻辑功能的前提下,对组合逻辑电路进行优化,如串行转并行; » 减少扇出或者负载; 从数字物理版图实现的角度看 » 更换速度更快的标准单元(HVT – High Voltage Threshold, SVT – Standard Voltage Threshold, LVT – Low Voltage Threshold) 高、标准、低阈值电压 » 更换驱动能力更强的标准单元(X2, X4) » 跟换阻值更低的金属层以减少标准单元电路的负载和金属线网的延迟
➢ 增加Tskew:
在时钟路径上,插入buffer,增加时钟路径的延迟,但是不能影响hold timing。
◆ Hold time violation: ➢ 保持时间在静态时序分析时必须满足以下条件: ➢ Thold < Tcq + Tcomb - Tskew ➢ 如果hold time violation, 则上述公式不成立。
◆ Hold time violation solution:
➢ 增大Tcomb
在组合电路的数据传输路径上,插入延迟单元(buffer),增加组合逻辑延迟;但是当组合逻辑 延时增加时,setup time可能会出现违例。这时候就需要做平衡(balance)。由此可以看出setup 和hold time是相互制约的。
➢ 减小Tskew
时钟树调整,做好clock tree balance,hold就容易收敛。因为hold time与时钟周期没有关系。 固有属性是在某种工艺下说的!
◆ 总结:setup和hold是相互制约的。 修复hold之后,setup的裕量就会变小或者变成负值。因此时钟频率越高,setup和hold相互制约越严重,甚至会出现修复setup之后,hold就会违例,或者修复hold之后,setup就会违例的现象。
2.为什么触发器会存在setup和hold time的要求?
➢ 提示:研究触发器的结构。数字电路基本结构。
3.当setup和hold time violation发生时,会导致什么后果?
➢ 提示:亚稳态
4.什么是亚稳态?如何在异步电路设计中解决亚稳态的问题?
➢ 提示:跨时钟域时,一个信号如何处理,多根信号如何处理,大量数据传输如何处理等常见的异步电路设计方法
➢ 更详细内容可参加视频课程:http://www.eecourse.com/course/103或点击跳转https://blog.csdn.net/haojie_duan/article/details/110304907
5.Given the following design, please draw out the waveform of output Y
-
这个题目设置的s是Async preset异步置位(s=0时,输出1);还有最常见的Async reset异步复位(s=0时,输出0)
-
参考:
6、Please improve the following design to save power
-
这是涉及到低功耗设计,如果有人问你低功耗是什么,就可以简单回答:“减少0和1的翻转!”
-
这个题目考察的门控时钟,给了使能信号,时钟就去采集数据;如果没给使能信号,就不采集(时钟就不翻转?)
-
Async fifo design using Verilog
8.Design the schematic for the logic of New_en= eco_en ?(eco_mask ^ en): en;(Please ONLY use NAND2 cells, and try to use as less cells as possible
9、Optimize the timing paths
由于两块电路里面各个输入到输出的路径延时不一致,为了避免竞争冒险必须把各个并行的路径的延时做到一样。
可以优化到的最小的延时为 2ns+0.5ns = 2.5ns. 可以通过插入反相器,与非门,或非门等。
◆ 如果只是靠插入上述的门,只能实现非,故为了保证逻辑不变必须插入偶数个。
◆ 0.1ns与2ns之间差1.9ns,是奇数个,故可以通过插入18个反相器,外加一个MUX。
◆ 0.5ns与2ns之间差1.5ns,可以插入14个反相器,外加一个mux。
◆ 后面一个电路0.1n延时的路径可以插入4个反相器。故最大延时为2.5ns。
10、Write verilog code which supports following function: For a string A, detect the location of its letters in string B, and output the location of the last detected letter in string B. For ample sting A is “nvidia” and string B is “naabcdiaiccbvde” the last detected letter in B is v, so output 13.
1 //-----------------------------------------------------------
2 // FileName: sequence_checker.v
3 // Creator : kinglin
4 // E-mail : service@eecourse.com
5 // Function: sequence checker
6 // Update :
7 // Coryright: www.eecourse.com @ 2018-09-14
8 //-----------------------------------------------------------
9 module sequence_checker(
10 input clk,
11 input rst_n,
12 input in_valid,
13 input [7:0] d_in,
14 output reg [4:0] cout_num_s,
15 output o_valid
16 );
17 wire [7:0] stringA[0:5];
18 //reg [8*15:1] stringB;
19 assign stringA[0]="n";
20 assign stringA[1]="v";
21 assign stringA[2]="i";
22 assign stringA[3]="d";
23 assign stringA[4]="i";
24 assign stringA[5]="a";
25 //stringB="naabcdiaiccbvde";
26 parameter idle=3'b000,
27 s0=3'b001, // "n"
28 s1=3'b010, // "nv"
29 s2=3'b011, // "nvi"
30 s3=3'b100, // "nvid"
31 s4=3'b101, // "nvidi"
32 s5=3'b110; // "nvidia"
33
34 reg [2:0] next_state;
35 reg [2:0] state;
36 reg out_en;
37 reg [4:0] cout_num;
38 //reg [4:0]cout_num_s;
39
40 always @ (posedge clk or posedge rst_n) begin
41 if(!rst_n)
42 state <= idle;
43 else
44 state <= next_state;
45 end
46
47 always @ (*)
48 case(state)
49 idle: if(d_in==stringA[0] & in_valid) begin
50 next_state = s0;
51 out_en = 1;
52 end else begin
53 next_state = idle;
54 out_en = 0;
55 end
56 s0: if(d_in==stringA[1] & in_valid) begin
57 next_state = s1;
58 out_en = 1;
59 end else begin
60 next_state = s0;
61 out_en = 0;
62 end
63
64 s1: if(d_in==stringA[2] & in_valid) begin
65 next_state = s2;
66 out_en = 1;
67 end else begin
68 next_state = s1;
69 out_en = 0;
70 end
71 s2: if(d_in==stringA[3] & in_valid) begin
72 next_state = s3;
73 out_en = 1;
74 end else begin
75 next_state = s2;
76 out_en = 0;
77 end
78 s3: if(d_in==stringA[4] & in_valid) begin
79 next_state = s4;
80 out_en = 1;
81 end else begin
82 next_state = s3;
83 out_en = 0;
84 end
85 s4: if(d_in==stringA[5] & in_valid) begin
86 next_state = s5;
87 out_en = 1;
88 end else begin
89 next_state = s4;
90 out_en = 0;
91 end
92 s5: if(d_in==stringA[0] & in_valid)begin
93 next_state = s0;
94 out_en = 1;
95 end else begin
96 next_state = s5;
97 out_en = 0;
98 end
99 default:begin
100 next_state=idle;
101 out_en=0;
102 end
103 endcase
104
105 always @ (posedge clk or negedge rst_n) begin
106 if(!rst_n)
107 cout_num <= 5'd0;
108 else if(in_valid)
109 cout_num <= cout_num+1;
110 else
111 cout_num <= cout_num;
112 end
113
114 always @ (posedge clk or negedge rst_n) begin
115 if(!rst_n)
116 cout_num_s <= 5'd0;
117 else if(out_en)
118 cout_num_s <= cout_num;
119 else
120 cout_num_s <= cout_num_s;
121 end
122
123 reg in_valid_d;
124
125 always @( posedge clk or negedge rst_n ) begin
126 if( !rst_n )
127 in_valid_d <=1'b0;
128 else
129 in_valid_d <= in_valid;
130 end
131
132 assign o_valid = (~in_valid) & in_valid_d;
133
134 endmodule
11、c语言求解两个数组的交集和并集,并按照从小到大的顺序输出。
设计思想: 构建函数:1:sort排序函数,2: Intersection交集函数,3: union并集函数,4:main主函数 先对输出的两个输入数组按照从小到大的顺序排列,然后调用交集和并集函数实现运算,最后通过main主函数,打印运算的结果。
1 #include <stdio.h>
2 void SelectSort(int *nums,int numsSize);
3 int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize);
4 int* union1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize);
5 void SelectSort(int *nums,int numsSize){
6 int min,temp;
7 int i;
8 int j;
9 for(i=0;i<numsSize-1;i++){
10 min=i;
11 for(j=i+1;j<numsSize;j++){
12 if(nums[min]>nums[j]){
13 min=j;
14 }
15 }
16 if(min!=i){
17 temp=nums[min];
18 nums[min]=nums[i];
19 nums[i]=temp;
20 }
21 }
22 }
23
24 int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize)
25 {
26 int temp,i,j;
27 int *result=(int *)malloc(nums2Size*sizeof(int));
28
29 //选择排序
30 SelectSort(nums1,nums1Size);
31 SelectSort(nums2,nums2Size);
32
33 *returnSize=0;
34 temp=nums1[nums1Size-1]+1; //给temp赋一个不可能与nums1或nums2冲突的值
35 for(i=0,j=0;i<nums1Size&&j<nums2Size;){
36 if(nums1[i]>nums2[j]){
37 j++;
38 }
39 else if(nums1[i]<nums2[j]){
40 i++;
41 }
42 else{
43 if(temp!=nums1[i]){
44 result[(*returnSize)++]=nums1[i];
45 temp=nums1[i];
46 }
47 i++;
48 j++;
49
50 }
51 }
52 return result;
53 }
54
55 int* union1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize)
56 {
57 int temp,i,j;
58 int *result=(int *)malloc((nums2Size+nums1Size)*sizeof(int));
59
60 //选择排序
61 SelectSort(nums1,nums1Size);
62 SelectSort(nums2,nums2Size);
63
64 *returnSize=0;
65 temp=1000;
66 //temp=nums1[nums1Size-1]+1;
67 for(i=0,j=0;i<nums1Size||j<nums2Size;){
68 if(j!=nums2Size&&nums1[i]>nums2[j]){
69 result[(*returnSize)++]=nums2[j];
70 j++;
71 }
72 else if(i!=nums1Size&&nums1[i]<nums2[j]){
73 result[(*returnSize)++]=nums1[i];
74 i++;
75 }
76 else if(j==nums2Size&&nums1[i]>nums2[j]){
77 result[(*returnSize)++]=nums1[i];
78 i++;
79 }
80 else if(i==nums1Size&&nums1[i]<nums2[j]){
81 result[(*returnSize)++]=nums2[j];
82 j++;
83
84 }
85 else{
86 if(temp!=nums1[i]){
87 result[(*returnSize)++]=nums1[i];
88 temp=nums1[i];
89 }
90 i++;
91 j++;
92
93 }
94 }
95 return result;
96 }
97
98 int main(int argc, char *argv[])
99 {
100 int a[11]={1,2,3,4,5,6,7,8,9,10,11};
101 int i;
102 int b[10]={3,4,5,6,7,8,9,10,11,12};
103 int c=0;
104 int *p=intersection(&a[0],11,&b[0],10,&c);
105
106 printf("\n +++++ array a :\n");
107 for (i=0; i<11; i++) {
108 printf("%d\n", a[i]);
109 }
110
111 printf("\n +++++ array b :\n");
112 for (i=0; i<10; i++) {
113 printf("%d\n", b[i]);
114 }
115
116 printf("++++++ intersection of the array a & b\n");
117 for(i=0;i<c;){
118 printf("%d\n",p[i]);
119 i++;
120 }
121
122 int *p1=union1(&a[0],11,&b[0],10,&c);
123 printf("++++++ union1 of the array a & b\n");
124 for(i=0;i<c;){
125 printf("%d\n",p1[i]);
126 i++;
127 }
128 return 0;
129 }
130