Oh! You closed up the window, so you cannot see raining

[VHDL] HDLbits 1 - Getting Started

HDLBits HDLBits 是一系列小型電路設計的練習,用於使用 Verilog 硬體描述語言(HDL)進行數位硬體設計。 由教學的題型由淺入深,逐步建立起電路設計的技能。 每個問題都會要求讀者使用 Verilog 設計一個小電路。HDLBits 會對提交的程式碼作判讀。透過一組測試碼來進行向量模擬,並與解答比較,檢查正確性。 Catalog 1. Getting Started 2. Verilog Language 3. Circuits 4. Verification: Reading Simulations 5. Verification: Writing Testbenches 6. CS450 1 Getting Started \(\text{assign one}\) Build a circuit with no inputs and one output. The output should always drive 1 (or logic high). module top_module( output one); assign one = 1'b1; endmodule \(\text{assign zero}\) Build a circuit with no inputs and one output that outputs a constant 0. module top_module( output zero ); assign zero = 1'b0; endmodule

<span title='2022-05-28 00:10:20 +0800 +0800'>May 28, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu
Oh! You closed up the window, so you cannot see raining

[VHDL] HDLbits 2 - Verilog Language

1. Getting Started 2. Verilog Language 3. Circuits 4. Verification: Reading Simulations 5. Verification: Writing Testbenches 6. CS450 2 Verilog Language 2.1 Basics wire Create a module with one input and ont output that behaves like a wire module top_module( input in, output out); assign out = in; endmodule multi-in-out Create a module with 3 inputs and 4 outputs that behaves like wires that makes these connections: module top_module( input a,b,c, output w,x,y,z ); assign w = a; assign x = b; assign y = b; assign z = c; endmodule not gate Create a module that implements a NOT gate. module top_module( input in, output out ); assign out = ~in; endmodule and gate Create a module that implments an AND gate. module top_module( input a,b, output out ); assign out = a & b; endmodule nor gate Create a module that implements a NOR gate. A NOR gate is an OR gate with its output inverted. A NOR function needs two operators when written in Verilog. module top_module( input a,b, output out ); assign out = ~(a|b); endmodule xnor gate Create a module that implements a XNOR gate. module top_module( input a, b, output out ); assign out = ~(a^b); endmodule wire declaration Implement following circuits. Create two intermediate wires to connect the AND and OR gates together. Note that the wire that feeds the NOT gate is really wire out, so you do not necessarily need to declare a third wire here. Notice how wires are driven by exactly one source (output of a gate), but can feed multiple inputs. module top_module( input a,b,c,d, output out, out_n ); wire w1, w2; assign w1 = a & b; assign w2 = c & d; assign out = w1 | w2; assign out_n = ~out; endmodule 7458 The 7458 is a chip with four AND gates and two OR gates. Create a module with the same functionality as the 7458 chip. It has 10 inputs and 2 outputs. module top_module( input p1a, p1b, p1c, p1d, p1e, p1f, output p1y, intput p2a, p2b, p2c, p2d, output p2y ); wire w1a, w1b; wire w2a, w2b; assign w1a = p1a & p1b & p1c; assign w1b = p1d & p1e & p1f; assign p1y = w1a | w1b; assign w2a = p2a & p2b; assign w2b = p2c & p2d; assign p2y = w2a | w2b; endmodule 2.2 Vectors vector Build a circuit that has one 3-bit input, then outputs the same vector, and also splits it into three separate 1-bit outputs. Connect outputs o0 to the input vector’s position 0, o1 to position 1, etc. In a diagram, a tick mark with a number next to it indicates the width of the vector (or “bus”), rather than drawing a separate line for each bit in the vector. module top_module ( input wire [2:0] vec, output wire [2:0] outv, output wire o2, output wire o1, output wire o0 ); assign outv = vec; assign o0 = vec[0]; assign o1 = vec[1]; assign o2 = vec[2]; endmodule vector select Build a combinational circuit that splits an input half-word (16 bits, [15:0]) into lower [7:0] and upper [15:8] bytes. module top_module ( input [15:0] in, output [7:0] out_hi, output [7:0] out_lo ); assign out_hi = in[15:8]; assign out_lo = in[7:0]; endmodule vector swap A 32-bit vector can be viewed as containing 4 bytes (bits [31:24], [23:16], etc.). Build a circuit that will reverse the byte ordering of the 4-byte word. AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa This operation is often used when the endianness of a piece of data needs to be swapped, for example between little-endian x86 systems and the big-endian formats used in many Internet protocols. module top_module ( input [31:0] in, output [31:0] out ); assign out[31:24] = in[ 7: 0]; assign out[23:16] = in[15: 8]; assign out[15: 8] = in[23:16]; assign out[ 7: 0] = in[31:24]; endmodule vector gates uild a circuit that has two 3-bit inputs that computes the bitwise-OR of the two vectors, the logical-OR of the two vectors, and the inverse (NOT) of both vectors. Place the inverse of b in the upper half of out_not (i.e., bits [5:3]), and the inverse of a in the lower half. module top_module ( input [2:0] a, input [2:0] b, output [2:0] out_or_bitwise, output out_or_logical, output [5:0] out_not ); assign out_or_bitwise = a | b; assign out_or_logical = a || b; assign out_not[2:0] = ~a; assign out_not[5:3] = ~b; endmodule gate-prefix vector Build a combinational circuit with four inputs, in[3:0]. There are 3 outputs: out_and: output of a 4-input AND gate. out_or: output of a 4-input OR gate. out_xor: outout of a 4-input XOR gate. module top_module ( input [3:0] in, output out_and, output out_or, output out_xor ); assign out_and = & in; assign out_or = | in; assign out_xor = ^ in; endmodule vector concatenate Given several input vectors, concatenate them together then split them up into several output vectors. There are six 5-bit input vectors: a, b, c, d, e, and f, for module top_module ( input [4:0] a, b, c, d, e, f, output [7:0] w, x, y, z ); assign {w, x, y, z} = {a, b, c, d, e, f, 2'b11}; endmodule vector reverse Given an 8-bit input vector [7:0], reverse its bit ordering. module top_module( input [7:0] in, output [7:0] out ); assign {out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7]} = in endmodule module top_module( input [7:0] in, output [7:0] out ); always @(*) begin for (int i=0; i<8; i++) out[i] = in[8-i-1]; end endmodule module top_module( input [7:0] in, output [7:0] out ); generate genvar i; for (i=0; i<8; i = i+1) begin: my_block_name assign out[i] = in[8-i-1]; end endgenerate endmodule vector replication Build a circuit that sign-extends an 8-bit number to 32 bits. This requires a concatenation of 24 copies of the sign bit (i.e., replicate bit[7] 24 times) followed by the 8-bit number itself. module top_module ( input [7:0] in, output [31:0] out ); assign out = {{24{in[7]}}, in}; endmodule vector replication2 Given five 1-bit signals (a, b, c, d, and e), compute all 25 pairwise one-bit comparisons in the 25-bit output vector. The output should be 1 if the two bits being compared are equal. module top_module ( input a, b, c, d, e, output [24:0] out ); assign out = ~{{5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}}} ^ {5{a,b,c,d,e}}; endmodule 2.3 Modules: Hierarchy By now, you’re familiar with a module, which is a circuit that interacts with its outside through input and output ports. Larger, more complex circuits are built by composing bigger modules out of smaller modules and other pieces (such as assign statements and always blocks) connected together. This forms a hierarchy, as modules can contain instances of other modules. ...

<span title='2022-05-28 00:10:20 +0800 +0800'>May 28, 2022</span>&nbsp;·&nbsp;27 min&nbsp;·&nbsp;Rain Hu
Oh! You closed up the window, so you cannot see raining

[VHDL] HDLbits 3 - Circuits

1. Getting Started 2. Verilog Language 3. Circuits 4. Verification: Reading Simulations 5. Verification: Writing Testbenches 6. CS450 3 Circuits 3.1 Combinational Logic 3.1.1 Basic Gates Wire module top_module ( input in, output out); assign out = in; endmodule GND module top_module ( output out); assign out = 1'b0; endmodule NOR module top_module ( input in1, input in2, output out); assign out = ~(in1|in2); endmodule Another Gate ...

<span title='2022-05-28 00:10:20 +0800 +0800'>May 28, 2022</span>&nbsp;·&nbsp;18 min&nbsp;·&nbsp;Rain Hu
Oh! You closed up the window, so you cannot see raining

[VHDL] HDLbits 4 - Verification: Reading Simulations

4 Verification - Reading Simulations 4.1 Finding bugs in code 4.2 Build a circuit from a simulation waveform 1. Getting Started 2. Verilog Language 3. Circuits 4. Verification: Reading Simulations 5. Verification: Writing Testbenches 6. CS450

<span title='2022-05-28 00:10:20 +0800 +0800'>May 28, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu
Oh! You closed up the window, so you cannot see raining

[VHDL] HDLbits 5 - Verification: Writing Testbenches

5 Verification - Writing Testbenches 1. Getting Started 2. Verilog Language 3. Circuits 4. Verification: Reading Simulations 5. Verification: Writing Testbenches 6. CS450

<span title='2022-05-28 00:10:20 +0800 +0800'>May 28, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu
Oh! You closed up the window, so you cannot see raining

[VHDL] HDLbits 6 - CS450

6 CS450 1. Getting Started 2. Verilog Language 3. Circuits 4. Verification: Reading Simulations 5. Verification: Writing Testbenches 6. CS450

<span title='2022-05-28 00:10:20 +0800 +0800'>May 28, 2022</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;Rain Hu
Oh! You closed up the window, so you cannot see raining

[VHDL] Verilog Hardware Description Language

1 Verilog HDL 1.1 Verilog 簡介 一套硬體描述語言 輔助設計數位系統 描述電路的行為 電子自動化工具 類似C語言的硬體描述語言 易學、容易接受 高階行為描述 切勿使用軟體思維(循序)撰寫(硬體描述語言多是並行的) 支援多種硬體層級的描述方式 從低階到高階模式 依照不同的方法設計 支援階層式的設計方法 樹狀式的設計結構 由繁化簡 1.2 Verilog 的模型 1.2.1 電晶體層級 Transistor Level 或低階交換層次模型(Switch Level Model) Verilog 最低階的層次模型 電路是由開關與電晶體所組成 一般不會採取低階的層級來進行設計 1.2.2 邏輯閘層級 Gate Level 使用基本的邏輯閘元件 AND、OR、NOT 邏輯電路圖 1.2.3 資料流層級 Data Flow Level 描述電路中資料的處理方式 資料如何在電路中運算及傳送 輸入持續驅動輸出 運算式 如:out = a + b + c 1.2.4 行為模型 Behavior Level Verilog 最高階的層次模型 不需考慮硬體元件的特型,只需放在模組的功能描述 很像 C 語言 合成軟體工具 1.2.5 結構式模型 Structure Level 引用硬體模組的模式 類似邏輯閘層次模型 支援階層式設計法 將複雜電路分為層狀結構 架構上類似樹狀結構 Bottom-up:元件→子模組→設計目標 Top-Down:設計目標→子模組→元件 Mixed:設計目標→子模組←元件(常用於大型複雜系統) \( \boxed{\text{Full Adder}} \begin{cases} \boxed{\text{Half Adder}} \begin{cases} \boxed{\text{XOR}}\\ \boxed{\text{AND}} \end{cases}\\ \boxed{\text{Half Adder}} \begin{cases} \boxed{\text{XOR}}\\ \boxed{\text{AND}} \end{cases}\\ \boxed{\text{OR}} \end{cases}\\ \text{設計目標}\qquad\qquad\text{子模組}\qquad\text{元件} \) 1.3 Verilog 語法詞彙 由一連串的標記(token)所組成 識別字(identifiers) 關鍵字(keywords) 字串(strings) 註解(comments) 空白(whitespace) 數值(numbers) 1.3.1 識別字(identifiers) 描述電路行為所使用的自訂物件 不違反命名規則,工程師自行定義的物件名稱 命名規則 字母、數字、底線_或是錢字號$所組合而成。 開頭只能使用字母或底線。 識別字是有大小寫之分的。 舉例 Shift_reg_b (Valid) _bus123 (Valid) $error_condition (Invalid) NT$899 (Valid) 3_bit_data (Invalid) 1.3.2 關鍵字(keywords) 描述電路語法所保留的一組特殊名稱的標記 定義語言的結構來描述電路 輸入(input)、輸出(output) 資料型態、電路行為 所有關鍵字都必須使用小寫表示 不可當作識別字使用 常見關鍵字 \(\begin{array}{|l|l|l|l|l|l|}\hline \text{always}&\text{and}&\text{assign}&\text{begin}&\text{buf}&\text{bufif0}\\\hline \text{bufif1}&\text{case}&\text{casex}&\text{casez}&\text{cmos}&\text{default}\\\hline \text{defparam}&\text{else}&\text{end}&\text{endcase}&\text{endfunction}&\text{endmodule}\\\hline \text{endtask}&\text{event}&\text{for}&\text{forever}&\text{fork}&\text{function}\\\hline \text{highz0}&\text{highz1}&\text{if}&\text{initial}&\text{inout}&\text{input}\\\hline \text{integer}&\text{join}&\text{module}&\text{nand}&\text{negedge}&\text{nmos}\\\hline \text{nor}&\text{not}&\text{notif0}&\text{notif1}&\text{or}&\text{output}\\\hline \text{parameter}&\text{pmos}&\text{posedge}&\text{pull0}&\text{pull1}&\text{pulldown}\\\hline \text{pullup}&\text{rcmos}&\text{real}&\text{realtime}&\text{reg}&\text{repeat}\\\hline \text{rnmos}&\text{rpmos}&\text{rtran}&\text{rtranif0}&\text{rtranif1}&\text{strong0}\\\hline \text{string1}&\text{supply0}&\text{supply1}&\text{task}&\text{time}&\text{tran}\\\hline \text{tranif0}&\text{tranif1}&\text{tri}&\text{tri0}&\text{tri1}&\text{triand}\\\hline \text{trior}&\text{trireg}&\text{wait}&\text{wand}&\text{weak0}&\text{weak1}\\\hline \text{while}&\text{wire}&\text{wor}&\text{xnor}&\text{xor}\\\hline \end{array}\) 1.3.3 字串(strings) 一連串字元(character)組成的單一個體 可含有字母、數字、及一些特殊字元 字串的所有字元必須在同一行上,並在雙引號之間 1.3.4 註解(comments) 程式碼中加入說明文字 可讀性(readability) 文件化(documentation) 版權宣告(license declaration) 以//開頭的單行註解(one-line comment) 以/*為開頭,並以*/為結尾的多行註解(multiple-line comment) 多行註解不支援巢狀結構 1.3.5 空白(whitespace) 區隔不同物件 空格(blank spaces,\b) 欄位(tabs,\t) 換行(newlines,\n) 除字串內空白,註解與空白在編譯與合成時會被忽略 1.3.6 數值(numbers) Verilog 有兩種數值表示法 固定長度(sized): 定義位元寬度 <size>'<bsase format><number> <size>:十進位來表示此數的位元數(bits) <base format>:定義進制 'H|'h:十六進制 'D|'d:十進制 'O|'p:八進制 'B|'b:二進制 <number>:用<base format>來表示數值 若為負號,將-放在<size>前面 舉例: 18'h47CB:18 bits 的十六進位數 47CB 13'h47CB:13 bits 的十六進位數(因未給定高位元自動補0) 7CB 12'd1023:12 bits 的十進位數 1023 9'o723:9 bits 的八進位數 723 5'b11101:5bits 的二進位數 11101 5'b1xx01:含有 unknown values 的表示法 不定長度(unsized): 未定義位元寬度 ‘<base format><number 不使用<size>規定位元長度 使用 HDL 編譯器內定的長度(32bit的寬度) 沒有寫明<base format>,則內定為十進制 舉例: 'h47CB:32 bits 的十六進位數 47CB 1023:32 bits 的十進位數 1023 'o723:32 bits 的八進位數 723 'b11101:32 bits 的二進位數 11101 Verilog 有四種數值位準(value level) \(\begin{array}{|c|l|}\hline \text{數值位準}&\text{實際電路狀態}\\\hline \text{0}&\text{邏輯0,假(false),接地}\\\hline \text{1}&\text{邏輯1,真(true),接壓電源}\\\hline \text{x}&\text{不確定值(unknown value)}\\\hline \text{z}&\text{高阻抗(high impedance),浮接狀態(floating state)}\\\hline \end{array} \) 1.4 Verilog 資料物件與型態 資料物件(data objects) 描述行為過程中所使用的訊號載具 一個物件經過處理再傳到另一個物件 資料型態(data type) 定義資料物件的類型 接線、暫存器、參數等 1.4.1 接線(Nets) 接線(nets)是連接實體元件的連接線 要被驅動才能改變其內部的值 最主要的關鍵字是 wire 一個位元的純量(scalar) 多位元長度的向量(vector) 內定值為 z(高阻抗、浮接) 宣告方式 wire w; // 宣告一條接線,命名為w,內定預設值為z wire x = 1'b0; // 宣告一條接線,命名為x,並指定x為邏輯0 wire a, b, c // 宣告三條接線,命名為a, b, c 1.4.2 暫存器(Registers) 抽象的資料儲存物件(有別於實體暫存器 D flip-flop) 保留一個數值直到下一次指定新值為止 觀念類似 C 語言中的變數 主要的關鍵字是 reg 一個位元的純量(scalar) 多位元長度的向量(vector) 內定值為 x(未知) \(\begin{array}{|l|l|}\hline \text{reg}&\text{可變動位元寬度的無號整數(unsigned integer variable)}\\\hline \text{integer}&\text{32位元寬度的有號整數(signed 32-bit integer variable),}\\ &\text{算術運算產生2補數結果(2’s complement results))}\\\hline \text{real}&\text{雙倍精確度之有號浮點數}\\ &\text{(signed floating-point variable with double precision)}\\\hline \text{time}&\text{64位元寬度的無號整數(unsigned 64-bit integer variable)}\\\hline \end{array}\) 設計電路請以reg為主,其他類型合成器可能不支援。 宣告方式 reg a; // 宣告 1 個 1 位元暫存器為 a,定位值為 1 位元的 x reg x, y; // 宣告 2 個宣存器,命名為 x, y integer count; // 宣告 1 個整數為 count,值可以為正負 real fraction; // 宣告 1 個浮點數為 fraction,值含小數點 1.4.3 純量與向量(scalar and vector) 純量(scalar) 一個位元的物件 向量(vector) 多個位元的物件 接線(ex. wire) 與 reg 內定一位元 [大數字:小數字]、[小數字:大數字]→[MSB:LSB] 宣告方式 wire a; // 宣告 1 個 1-bits 接線 wire [4:0] x; // 宣告 1 個 5-bits 接線 reg b; // 宣告 1 個 1-bits 暫存器 reg [0:7] y; // 宣告 1 個 8-bits 暫存器 reg [31:0] z; // 宣告 1 個 32-bits 暫存器 1.4.4 陣列(Array) 多個暫存器、接線的聚合體 索引值(index)定義聚合體中的個別物件 支援多維度的陣列 記憶體(memory)、暫存器檔案(register file) 陣列中暫存器、接線的個數 [大數字:小數字]、[小數字:大數字] 宣告方式 // mem_block 是一個包含 128 個暫存器的陣列, // 每個暫存器皆為 32 位元寬 reg [31:0] mem_block [127:0]; // mem_2D 是一個 2 維 4x64 的暫存器陣列, // 每個暫存器皆為 8 位元寬 reg [7:0] mem_2D [3:0][63:0]; 1.4.5 參數(parameter) 定義編譯合成電路時的常數 每次編譯合成前更改,編譯合成器會根據參數值產生相對應的電路 重複使用 關鍵字 parameter 宣告方式 parameter width = 4; wire [width-1:0] a, b; // 接線 a 和 b 的位元寬度,會隨著參數值的改變而變動 reg [width-1:0] y; // 暫存器 y 的位元寬度,會隨著參數值的改變而變動 1.5 模組(Module)、埠(Port) 1.5.1 模組(Module) 一個電路區塊、可以由其他模組組成 連接模組時 考慮模組的輸入與輸出介面 不需要考慮模組內部的詳細電路 電路設計時 只修改模組內部電路 不會改變電路外部及周遭的模組 模組內部的電路描述可包含 訊號資料型態宣告 引用其他模組(邏輯閘) assign 資料處理模型之描述 always 行為模型之描述 函數(function) 與 任務(task) 除訊號宣告需先描述,其他部分撰寫的順序,不影響電路行為 模組宣告 以關鍵字 module 為開頭,在其後加一個識別用的模組名稱(module name) 再來是輸入與輸出埠列(module terminal list)和埠列宣告,接著是模組內部關於電路的描述 以關鍵字 endmodule 做為模組結尾 支援階層`式的設計概念 module module_name(terminal_list) port_declaration(...) param_declaration(optional) data_type_declaration(wire, reg) other_module(logic_gate) assign data_flow_model always behavior_model function, task endmodule 1.5.2 埠(port) 終端點、模組與外界溝通的介面接點(門) 一個模組通常是經由一串的輸入輸出埠稱為埠列(terminal list)來與外界溝通 若模組與外界不需要溝通,則埠列也就不存在(封閉系統) 測試環境(test bench) 埠的宣告 埠的宣告可分為輸入埠(input)、輸出埠(output)、雙向埠(inout)三種。 埠的宣告型態內定為接線(net)的 wire,若需要將訊號儲存起來則埠號型態須宣告成暫存器 reg。 輸入埠和雙向埠只能是接線(net),不可宣告成暫存器。 輸出埠可以宣告成接線(net)或暫存器。 module full_adder(a, b, carry, sum); // 埠列 input [3:0] a, b; // 輸入埠(4位元向量) input carry // 輸入埠(1位元純量) output [4:0] sum; // 輸出埠(5位元向量) reg [4:0] sum; // 因輸出sum需儲存資料,故宣告成暫存器 ... endmodule 1.6 邏輯閘層次模型 利用關鍵字即可引用基本的邏輯閘元件 基本的邏輯閘關鍵字 and nand or nor not xor xnor 1.6.1 多個輸入邏輯閘(Multiple-Input Gates) and、nand、or、nor、xor、xnor 具有多個純量(scalar)的輸入,但是只有一個純量的輸出 多個輸入邏輯閘的輸出總是放在埠列(post list)的第一個位置,而輸入則是跟在輸出的後面 輸出必須透過接線(wire)連接,輸入無規定 多個輸入邏輯閘的別名可以加或是不加 使用方法 gate_type instance(out, in_1, in_2, in_3, ..., in_n); gate_type inst_1(out_1, in1_1, in1_2, in1_3, ..., in1_n), inst_2(out_2, in2_1, in2_2, in2_3, ..., in2_n), inst_3(out_3, in3_1, in3_2, in3_3, ..., in3_n), ... inst_m(out_m, in_m1, in_m2, in_m3, ..., in_mn); \(\begin{array}{ccc} \underbrace{\text{a, b, c, d}}_{\text{輸入}} \rightarrow \boxed{\text{Multiple-Input Gate}} \rightarrow \underbrace{\text{e}} _{\text{輸出}} \end{array} \) \(\text{and\quad a1(} \underbrace{\text{e}}_{\text{輸出}} \text{, } \underbrace{\text{a, b, c, d}} _{\text{輸入}} \text{);} \) 1.6.2 多個輸出邏輯閘(Multiple-Output Gates) not、buf ...

<span title='2022-05-01 17:37:22 +0800 +0800'>May 1, 2022</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;Rain Hu