3.1 請解釋D觸發器和Latch的區別,解釋同步復位和異步復位的區別及優缺點。
一、D觸發器和Latch的區別
Latch有電平觸發,非同步控制。在使能信號有效時Latch相當於通路,在使能信號無效時Latch保持輸出狀態。D觸發器由時鍾沿觸發,同步控制。
Latch容易產生毛刺,D觸發器則不易產生毛刺。
如果使用門電路來搭建Latch和D觸發器,則Latch消耗的門資源比D觸發器要少,這是Latch比D觸發器優越的地方。所以在ASIC中使用Latch的集成度比D觸發器高,但在FPGA中恰好相反,因為FPGA中沒有標准的Latch單元,但有D觸發器單元,一個Latch需要多個LE才能實現。
二、同步復位和異步復位的區別
異步復位:異步復位只要有復位信號系統馬上就復位,因此異步復位抗干擾能力差,有些噪聲也是能系統復位,因此有時候顯得不夠穩定,要想設計一個好的復位最好使用異步復位同步釋放。
同步復位:
優點:
有利於仿真器仿真;
可以使用所設計的系統成為100%同步時序電路,這大大有利於時序分析,而且綜合出來的fmax一般較高。
因為他只有在時鍾有效電平到來時才有效,所以可以濾掉高於時鍾頻率的毛刺。
缺點:
復位信號的有效時長必須大於時鍾周期,才能真正被系統識別並完成復位任務。同時還要考慮,諸如:clk skew,組合邏輯路徑延>時,復位延時等因素;
由於大多數的邏輯器件的目標庫內的DFF都只有異步復位端口,所以,倘若采用同步復位的話,綜合器就會在寄存器的寄存器的數據輸入端口插入組合邏輯,這樣就會耗費較多的邏輯資源。
異步復位:
優點:
大多數目標器件庫的DFF都有異步復位端口,因此采用異步復位可以節省資源;
設計相對簡單;
異步復位信號識別方便,而且可以很方便的使用FPGA的全局復位端口GSR。
缺點:
在復位信號釋放(release)的時候很容易出現問題,倘若復位釋放時恰好在時鍾有效沿附近,就很容易使寄存器輸出出現亞穩態,從而導致亞穩態。
復位信號容易收到毛刺影響。
3.2 解釋什么叫clock gating?並說明一下通常情況下為什么要做clock gating?簡單列舉通常實現的方法有哪些?
門控時鍾計數(clock gating)是一種非常簡單和有效的功耗控制方法,它的基本原理就是通過關閉芯片上暫時用不到的功能和它的時鍾,從而實現節省電流消耗的目的。 clk信號和clk_enable相與。
時鍾門控(Clock-Gating)一直以來都是降低微處理器功耗的重要手段,主要針對寄存器翻轉帶來的動態功耗。如何更加有效地設計時鍾門控對於最大限度地降低功耗,同時保證處理器的性能至關重要。多核多線程微處理器中,多個功能部件可能不是同時工作的,對於無執行任務的功能部件就可以將其時鍾關閉,減少其隨時鍾翻轉進行多余的內部寄存器翻轉,從而降低產生功耗的浪費和熱量聚集。
3.3 實現一個可以1-8分頻任意切換的分頻器,要求無論是奇數分頻還是偶數分頻,分頻后的時鍾的duty cycle都是50%。
1 //占空比模塊
2 module Duty_Cycle#( 3 parameter HIGH_TIME = 1, //高電平時間
4 LOW_TIME = 2, //低電平時間
5 BIT_WIDTH = 2 //位寬
6 )( 7 input clk, //時鍾
8 input rst_n, //異步復位
9 output reg clk_out //輸出
10 ); 11
12 reg [BIT_WIDTH-1:0] count; //計數器
13
14 always_ff @(posedge clk, negedge rst_n) begin
15 if(!rst_n) begin
16 count <= '0;
17 end
18 else if(count < HIGH_TIME) begin
19 count <= count + 1; 20 clk_out <= '1;
21 end
22 else if((count < HIGH_TIME+LOW_TIME-1) && (count >= HIGH_TIME))begin
23 clk_out <= '0;
24 count <= count + 1; 25 end
26 else if(count >= HIGH_TIME+LOW_TIME-1)begin
27 clk_out <= '0;
28 count <= '0;
29 end
30 else begin
31 clk_out <= clk_out; 32 count <= count; 33 end
34 end
35
36 endmodule
37
38 //分頻模塊===================================================
39 module Frequency_Divider#( 40 parameter DIV_COEFF = 3, //分頻系數
41 BIT_WIDTH = 2 //分頻系數位寬
42 )( 43 input clk, //時鍾
44 input rst_n, //復位
45
46 output clk_out //分頻時鍾
47 ); 48 //====================================================== 49 //奇偶判斷,0為偶
50 wire odd_even; 51 wire [BIT_WIDTH-1:0] div_coeff; 52
53 assign div_coeff = DIV_COEFF; 54 assign odd_even = div_coeff[0]; 55 //====================================================== 56 //計算高低占空比時間
57 parameter HIGH_TIME = DIV_COEFF/2; 58 parameter LOW_TIME = DIV_COEFF-HIGH_TIME; 59 //====================================================== 60 //根據奇偶分頻分配時鍾
61 reg clk_p,clk_n; 62
63 always_comb begin
64 if(odd_even)begin
65 clk_p = clk; 66 clk_n = ~clk; 67 end
68 else begin
69 clk_p = clk; 70 clk_n = clk; 71 end
72
73 end
74
75 wire clk_out_p,clk_out_n; 76
77 Duty_Cycle#( 78 .HIGH_TIME (HIGH_TIME), 79 .LOW_TIME (LOW_TIME), 80 .BIT_WIDTH (BIT_WIDTH) 81 )u1_Duty_Cycle( 82 .clk (clk_p), 83 .rst_n (rst_n), 84 .clk_out (clk_out_p) 85 ); 86
87 Duty_Cycle#( 88 .HIGH_TIME (HIGH_TIME), 89 .LOW_TIME (LOW_TIME), 90 .BIT_WIDTH (BIT_WIDTH) 91 )u2_Duty_Cycle( 92 .clk (clk_n), 93 .rst_n (rst_n), 94 .clk_out (clk_out_n) 95 ); 96
97 assign clk_out = clk_out_p | clk_out_n; 98
99 endmodule
3.5 現有三個輸入信號分別是a,b,c,並且前級DFF Clock到a,b,c的延時分別是Ta,Tb,Tc(Ta>Tb>Tc),請用兩個二輸入選擇器對a,b,c實現三輸入選擇輸出,畫電路圖並解釋設計思路,不需要考慮Clock Skew的影響。
3.6 請畫出下列數字電路D觸發器輸出Q0,Q1的波形圖(復位之后Q0,Q1均為0,畫出復位后8個時鍾周期)。
可見,Q0(n+1)=~Q1(n) ;Q1(n+1)= Q0(n) ^ Q1(n) = ~Q1(n-1) ^ Q1(n) = Q1(n-1) ~^ Q1(n) ,即Q1的前一狀態與前前狀態同或。
Q0 | Q1 | |
---|---|---|
RESET | 0 | 0 |
第一個CLK | 1 | 0 |
第二個CLK | 1 | 1 |
第三個CLK | 0 | 0 |
第四個CLK | 1 | 0 |
第五個CLK | 1 | 1 |
第六個CLK | 0 | 0 |
第七個CLK | 1 | 0 |
第八個CLK | 1 | 1 |
可看出Q0、Q1復位后出現00、10、11循環。
3.7 分析代碼覆蓋率時,verilog語句if(a||b&&c)有那幾個條件需要覆蓋?請用表格列出每種狀況下a/b/c的值(a/b/c均為bit類型,如果是0或1都無所謂,請用“-”表示)。
A | B | C | A||B&&C (邏輯與優先於邏輯或) |
---|---|---|---|
1 | - | - | 1 |
0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
- | 1 | 1 | 1 |
a為真或b&&c為真,結果為真; a和b&&c都為假時,結果為假。
3.8 使用任意一種編程或腳本語言(C,Verilog,SystemVerilog,shell,perl,Python)實現32位十六進制轉化為二進制數(如abcd0123->10101011110011010000000100100011)。
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 void HextoTwo(int num) 5 { 6 int res; 7 int i = 0; 8 char buf[BUFSIZ][5] = {"0000"}; 9 char reference[16][5] = {"0000","0001","0010","0011",\ 10 "0100","0101","0110","0111",\ 11 "1000","1001","1010","1011",\ 12 "1100","1101","1110","1111"}; 13
14 while(num / 16 != 0) 15 { 16 res = num % 16; 17 strcpy(buf[i++], reference[res]); 18 num = num / 16; 19 } 20
21 res = num % 16; 22 strcpy(buf[i++], reference[res]); 23
24 while(i > 0) 25 printf("%s ", buf[--i]); 26 } 27 //采用遞歸
28 void HextoTwo(int num) 29 { 30 int remainder; 31 char buf[16][5] = {"0000","0001","0010","0011",\ 32 "0100","0101","0110","0111",\ 33 "1000","1001","1010","1011",\ 34 "1100","1101","1110","1111"}; 35 if(0 == num) 36 return; 37
38 remainder = num % 16; 39 HextoTwo(num >> 4); 40 printf("%s ", buf[remainder]); 41 } 42
43 int main() 44 { 45 int num = 0xfa; 46 HextoTwo(num); 47 return EXIT_SUCCESS; 48 }
3.9 使用C或Verilog/SystemVerilog,定義並實現一個函數,傳遞三個int類型參數A,B,C,函數返回后,A的值不變,B的值變為A+B,C的值變為A-C,請寫出函數原型定義與函數體的實現。
1 module A; 2
3 int A; 4 int B; 5 int C; 6
7 initial begin
8 A=1; 9 B=2; 10 C=3; 11
12 $display("%d,%d,%d",A,B,C); 13 #1; 14
15 func1(A,B,C); 16
17 $display("%d,%d,%d",A,B,C); 18 end
19 //System Verilog中ref表明參數是使用引用傳遞當函數需要返回多個值或者任務需要返回一個以上值的時候,通過引用傳遞就用得上。
20 function automatic viod func1(ref int A,ref int B,ref int C); 21 A=A; 22 B=A+B; 23 C=A-C; 24 endfunction
25 endmodule
CPU通過APB接口讀寫寄存器,interrupt為中斷輸出信號。模塊內有如下寄存器,每個bit對應一種中斷源,當某個中斷enable位配置為1時,內部邏輯被允許對中斷status位進行置位操作;當任意一位status被置位1,且其mask位為0時,則interrupt輸出為高電平。CPU通過APB將status位寫1清0。如果所有status位都被清0后,interrupt輸出低電平。
中斷使能寄存器reg_int_enable[7:0]; 中斷屏蔽寄存器reg_init_mask[7:0]; 中斷狀態寄存器reg_int_status[7:0](所有位都是W1C,即“寫1清0”)。
-
APB總線對三個寄存器任意一位讀寫操作功能測試;
-
reg_int_status寄存器任意一位W1C功能測試;
-
APB總線配置reg_int_enable寄存器任意一位為1,對應位status置位功能測試;
-
寄存器reg_int_enable和reg_int_status對應位置位時,且reg_int_mask對應位置0時,信號interrupt拉高功能測試;
-
reg_int_status寄存器所有位W1C操作,信號interrupt拉低功能測試。