Verilog 學習歷程: 28 題: Xor 可以選擇讓輸入是否要反向耶,B 如果選擇 1,則 A 會被反向,B 選擇 0,A 不變。XOR 可用一個反向器和多工器相替換。 A B A,B 的減法可用 A+~B+1 實現。 30 題: Blocking vs. Non-Blocking Assignment There are three types of assignments in Verilog: • Continuous assignments (assign x = y;). Can only be used when not inside a procedure ("always block"). • • Procedural blocking assignment: (x = y;). Can only be used inside a procedure. Procedural non-blocking assignment: (x <= y;). Can only be used inside a procedure. 32 題:always if2 設計電路時,你必須首先想到在電路方面: • 我想要這個邏輯門 • 我想要一個具有這些輸入並產生這些輸出的邏輯組合塊 • 我想要一個邏輯組合塊,然後是一組觸發器 你不能做的是先寫代碼,然後希望它生成一個合適的電路。 • 如果(cpu_overheated)那麼 shut_off_computer = 1; • If (~arrived) then keep_driving = ~gas_tank_empty 38 題: & a[3:0] // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf) | b[3:0] // OR: b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0) ^ c[2:0] // XOR: c[2]^c[1]^c[0] 把每個位元抓起來一起做運算,可用上面的方法化簡。 42 題 module top_module( input [99:0] a, b, input cin, output reg [99:0] cout, output reg [99:0] sum ); always@(*)begin:loop1 integer i; sum[0] =a[0]^b[0]^cin; cout[0] = a[0]&b[0] | a[0]&cin | b[0]&cin ; for (i=1;i<100;i=i+1) sum[i] = a[i]^b[i]^cout[i-1]; end //有一點在 verilog(硬體)很有趣,上下兩個 always block,他們合成電路後執行是平 行的,簡單來說就是我只是把它們的接線關係描述出來而已,並非像 C 一樣是順 序執行。 always@(*)begin:loop2 integer j; for (j=1;j<100;j=j+1) cout[j] = a[j]&b[j] | a[j]&cout[j-1] | b[j]&cout[j-1]; end endmodule 54 題: 可用 XNOR 來判斷兩數是否相等,例如兩數皆為 4BIT,XNOR 後的結果如果通通為 1,也就是 1111,那麼這兩數相等 55 題: Task 的使用很像模組?但和模組又有甚麼不同呢? 。 59 題: module top_module ( input [3:0] in, output [2:0] out_both, output [3:1] out_any, output [3:0] out_different ); // Use bitwise operators and part-select to do the entire calculation in one line of code // in[3:1] is this vector: in[3] in[2] in[1] // in[2:0] is this vector: in[2] in[1] in[0] // Bitwise-OR produces a 3 bit vector. // Assign this 3-bit result to out_any[3:1]: | o_a[3] | o_a[2] | o_a[1] // Thus, each output bit is the OR of the input bit and its neighbour to the right: // e.g., out_any[1] = in[1] | in[0]; // Notice how this works even for long vectors. assign out_any = in[3:1] | in[2:0]; assign out_both = in[2:0] & in[3:1];//位元對位元直接做檢測,注意是他是用 in[2]&in[3],in[1]&in[2],in[0]&in[1]直接將位置錯開了,挺有趣的可以多想想。 // XOR 'in' with a vector that is 'in' rotated to the right by 1 position: {in[0], in[3:1]} // The rotation is accomplished by using part selects[] and the concatenation operator{}. assign out_different = in ^ {in[0], in[3:1]};這和上面的一樣把位置錯開後,不一 樣的是 in[3]^in[0],題目有說要做成循環的 endmodule 63 題: out = '1;//可用 ‘1 表示 out 全部位元都為 1,這樣寫就不用管他幾位元了,假他 16bit,照我之前的寫法我會寫 16’hffff,太慢了。 always @(*) begin out = '1; // '1 is a special literal syntax for a number with all bits set to 1. // '0, 'x, and 'z are also valid. // I prefer to assign a default value to 'out' instead of using a // default case. case (sel) 4'h0: out = a; 4'h1: out = b; 4'h2: out = c; 4'h3: out = d; 4'h4: out = e; 4'h5: out = f; 4'h6: out = g; 4'h7: out = h; 4'h8: out = i; endcase end endmodule 有設初始條件就不用在 case 裡加入 default 了 64 題: 256 to 1MUX,in 有 256bit =2^m => m=8bit,故選擇線為 8bit 65 題: 當要做位元切片時,Verilog 裡沒有這樣的寫法 out = in[sel*4+3:sel*4]; 可改成 assign out = in[sel*4 +: 4]; // 从 sel*4 开始,选择比特序号大于 sel*4 的 4 位比特,相当于 [sel*4+3:sel*4] assign out = in[sel*4+3 -: 4]; // 从 sel*4+3 开始,选择比特序号小于 sel*4+3 的 4 位比特,相当于 [sel*4+3:sel*4] 注意!! 每次 quatus 跑波型驗證時,只要修改完 code,跑驗證時第一 次都會是上一個 code 的結果,所以要記得跑第二次驗證才知 道 code 有沒有改對。 70 題: 要檢查兩補數有無溢位 ==> 先檢查符號位是否一樣(只有符號一樣的數才有溢 位的情況),在檢查運算結果是否和倆數的符號是否一樣,不一樣就是溢位,ex 兩 個負的加到變正的??太奇怪了一定溢位 71 題: module top_module( input [99:0] a, b, input cin, output cout, output [99:0] sum ); assign {cout,sum} = a+b+cin; //超狂寫法,不須注意中間 carry-out 信號,最後一位的 carry-out 信號自動填進 cout Endmodule 74 題: 注意他的 K-map 的上欄,跟我熟悉的順序不同,但只要相鄰兩項只有一位變化,那 邏輯就相等。 75 題: 看到棋盤 Kmap,就知道是 XOR 系列的,且他是在奇數個 1 才為 1,所以她是 xor。 76 題: Pos=>關注為 1 的項,把基項 or 起來,每個基項都是各個輸入 and 在一起 Sop=>關注為 0 的項,把基項 and 起來,每個基項都是各個輸入 or 在一起 80 題: 網站提供的解答和我的想法相差蠻多的,值得看。 88 題: 同步 reset(synchronous reset) => 跟著時脈邊緣決定要不要 reset 非同步 reset (asynchronous reset)=> 不跟著時脈即可自行觸發 reset 92 題 訊號中繼站不能算是 in 或 output z = ~(z1 | z2 | z3);//z 並不是在時脈觸發才會更動值,而是一直在更動,所以她是 個組合邏,不能放在 always block 內 95 題: 判斷倆數是否相等可用 XOR Always block 裡的敘述到底是順序的還是平行的呢? Ans: 如果使用 blocking ( = ) 則敘述是會順序執行的, non-blocking( <= ) 則是平行執行的,會先把右側資料準備好,然後在觸發條件成立 時把敘述內右側的值賦值到左側 奇數除頻器 外加兩個由 clk 的正負緣所產生的 clk,來實現奇數除頻器 原理:假設要做 1/25 的除頻器, module divn ( 11 input clk, 12 input rst_n, 13 output o_clk 14 ); 15 16 parameter WIDTH = 3; 17 parameter N = 6; 18 19 reg [WIDTH-1:0] cnt_p; 20 reg [WIDTH-1:0] cnt_n; 21 reg clk_p; 22 reg clk_n; 23 24 assign o_clk = (N == 1) ? clk ://N=1 為不除頻 25 (N[0]) ? (clk_p | clk_n) : (clk_p);//N[0]為 1,為奇數,反之為 偶數 26 27 always@(posedge clk or negedge rst_n) begin 28 if (!rst_n) 29 30 cnt_p <= 0; else if (cnt_p == (N-1))//0~N-1 總長為 N 31 32 cnt_p <= 0; else 33 cnt_p <= cnt_p + 1; 34 end 35 36 always@(posedge clk or negedge rst_n) begin 37 38 39 if (!rst_n) clk_p <= 1; else if (cnt_p < (N>>1))//假如除 25,則 clk_p 為 1 的時間要在 0~12 40 41 clk_p = 1; else 42 clk_p = 0; 43 end 44 45 always@(negedge clk or negedge rst_n) begin 46 if (!rst_n) 47 48 cnt_n <= 0; else if (cnt_n == (N-1)) 49 50 cnt_n <= 0; else 51 cnt_n <= cnt_n + 1; 52 end 53 54 always@(negedge clk or negedge rst_n) begin 55 if (!rst_n) 56 57 clk_n <= 1; else if (cnt_n < (N>>1)) //假如除 25,則 clk_n 為 1 的時間要在 0~12,13+13-1=25(- 1 是因為 clk_n 和 cnt_p 會重疊,所以總共是 25 個 clk) 58 59 clk_n = 1; else 60 clk_n = 0; 61 end 62 63 endmodule ---------------------------------------------------如果要設計一個數值會循環的功能,可利用%來完成,例如我要讓 X 從 0~9,9 之後再+1 就變 10,這時個位 數可用 x%10 來實現循環的功能 ---------------------------------------------------- 注意!!input 不能使用 reg 的資料型態!! 做兩次 xor 會是原來的值 ---------------------------------mealy 機和 moore 機的差別: mealy 機的輸出和輸入有關,輸入改變的話輸出也會跟著變(再最後 不用等 clk),而 moore 機輸入不直接和輸出有關係 --------------------------------------狀態機: n 個狀態要用 x 個暫存器? Ans:滿足 n≦2^x 的最小整數即可, 假如 n=5,則 x=3 Always@(posedge clk)這個 blk 一定會合出有關 D 型正反器的 東西,這樣想,這個 blk 是在正緣 clk 才會動作, e.g. state <= next_state, 不是正緣 clk 時 state 會是甚麼值?? 想當然他只能維持之前的值,所以需要一個儲存元件(正反器) ------------------------------------------------狀態機: 要想清楚在某一時刻的 clk 的 state 或 next_state 和其他控制 動作的時序的關係,要想好到底該以 state 還是 next_state 為 sensitivity list