# HDLBits Notes ## AlwaysBlock ```verilog always @(posedge clk) begin LHS <= RHS; ME <= (A&B); end assign ME2 = ME; ``` 在CLK 正緣的時候,根據觀看變數的角色,時間關係會變化。 在同一個CLK 更新的變數。 例如說ME 是LHS(輸出)的變數看過去,LHS 就是 RHS_OLD,RHS(輸入)就是 LHS_NEXT。 不同CLK 更新的變數。 例如說ME2 是assign 的變數的時候,ME 就是 ME2_NEW,因為ME 是RHS 並且是任何時候都更新。 ## AlwaysBlock https://hdlbits.01xz.net/wiki/Alwaysblock2 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. ## JK Filp Flop 1. **Start with the JK flip-flop truth table** (first table). 2. **Expand it** to include the current state $Q_{\text{old}}$ (second table). 3. **Replace Q with D($Q_{\text{next}}$)** — because for a D flip-flop, 最簡單的描述方式 | J(In) | K(In) | Q(Out) | |:-----:|:-----:|:-----------------:| | 0 | 0 | $Q_{\text{old}}$ | | 0 | 1 | 0 | | 1 | 0 | 1 | | 1 | 1 | ~$Q_{\text{old}}$ | 把結果都寫出來 | J(In) | K(In) | $Q_{\text{old}}$(In) | Q(Out) | |:-----:|:-----:|:--------------------:|:------:| | 0 | 0 | 0 | 0 | | 0 | 0 | 1 | 1 | | 0 | 1 | 0 | 0 | | 0 | 1 | 1 | 0 | | 1 | 0 | 0 | 1 | | 1 | 0 | 1 | 1 | | 1 | 1 | 0 | 1 | | 1 | 1 | 1 | 0 | **Flip Flop is Update Q with Q next** > 在推理JK Filp Flop 的時候有使用到Q_OLD 的概念。 原本預期直覺去想會是 Q <= Q_OLD。 但是不能放在Always Block 當中。 > 目標是 Q 是每一個CLK 才更新,需要放在Always Block 當中,Q 必須要成為 LHS。 又根據Always Block 的邏輯,只能在(輸入)右邊放NEXT,(輸出)左邊放OLD (NEW)。 >然後Q 跟 Q_OLD 是接在一起只是中間多了REG,所以Q 的時間角色因為其實可以交換去看,原本是OLD(In) 的人變成NOW(Out),原本NOW(Out) 的人變成NEXT(In)。 **嘗試把表格交換個時間的角度去看,看看能不能解決問題。** > 因為 J 與 K 跟時間沒關係,所以不用改變。 > 因為 J K 會決定 Q ,所以用 Assign 的方式把 J K 輸入到Q_NEXT 當中。 > 在Always Block 當中 Q <= Q_NEXT 符合預期,也合理。 > 然後 J K 跟時間沒關係,指定給Q 效果不正確,所以指定給Q_NEXT。 | J(In) | K(In) | Q(Out) | D($Q_{\text{next}}$)(In) | |:-----:|:-----:|:------:|:------------------------:| | 0 | 0 | 0 | 0 | | 0 | 0 | 1 | 1 | | 0 | 1 | 0 | 0 | | 0 | 1 | 1 | 0 | | 1 | 0 | 0 | 1 | | 1 | 0 | 1 | 1 | | 1 | 1 | 0 | 1 | | 1 | 1 | 1 | 0 | ### Sum of product Each minterm is **AND** of all variables (negating if `0` in the row): **Row 2** $(J=0, K=0, Q=1)$: $\overline{J} \cdot \overline{K} \cdot Q$ **Row 5** $(J=1, K=0, Q=0)$: $J \cdot \overline{K} \cdot \overline{Q}$ **Row 6** $(J=1, K=0, Q=1)$: $J \cdot \overline{K} \cdot Q$ **Row 7** $(J=1, K=1, Q=0)$: $J \cdot K \cdot \overline{Q}$ $$ D = (\overline{J} \cdot \overline{K} \cdot Q) + (J \cdot \overline{K} \cdot \overline{Q}) + (J \cdot \overline{K} \cdot Q) + (J \cdot K \cdot \overline{Q}) $$ **Group terms with** $\overline{Q}$: $$ J \cdot \overline{K} \cdot \overline{Q} + J \cdot K \cdot \overline{Q} = J \cdot \overline{Q} \cdot (\overline{K} + K) = J \cdot \overline{Q} $$ **Group terms with** $Q$: $$ \overline{J} \cdot \overline{K} \cdot Q + J \cdot \overline{K} \cdot Q = \overline{K} \cdot Q \cdot (\overline{J} + J) = \overline{K} \cdot Q $$ --- **Final simplified SOP equation:** $$ D = (J \cdot \overline{Q}) + (\overline{K} \cdot Q) $$ --- **Verilog** ```verilog wire D; // Combinational logic for JK → D mapping assign D = (J & ~Q) | (~K & Q); // D flip-flop always @(posedge clk) begin Q <= D; end ``` ## https://hdlbits.01xz.net/wiki/Edgedetect | $\text{in}$ | $\text{in}_\text{old}$ | $\text{pedge}$ | |:-----------:|:----------------------:|:--------------:| | 0 | 0 | 0 | | 0 | 1 | 0 | | 1 | 0 | 1 | | 1 | 1 | 0 | 因為從 pedge 要在這一個clk 更新,pedge 要放在LHS。 從LHS 的角度去看時間關係的話。LHS 是reg,會儲存上一次的 RHS 數值。 所以對於pedge 來講同一個CLK,LHS 對他來講是old,RHS 是new。 LHS <= RHS ### Sum of product $$ \text{pedge} = (\text{in}) \cdot (\overline{\text{in}_\text{old}}) $$ ```verilog reg [7:0] old_in; always @(posedge clk) begin old_in <= in; pedge <= in & ~old_in; end ``` ## https://hdlbits.01xz.net/wiki/Edgedetect2 | $\text{in}$ | $\text{in}_\text{old}$ | $\text{anyedge}$ | |:-----------:|:----------------------:|:----------------:| | 0 | 0 | 0 | | 0 | 1 | 1 | | 1 | 0 | 1 | | 1 | 1 | 0 | ### Sum of product **Row 1** $\text{anyedge} = (\text{in}) \cdot (\overline{\text{in}_\text{old}})$ **Row 2** $\text{anyedge} = (\overline{\text{in}}) \cdot (\text{in}_\text{old})$ ```verilog reg [7:0] old_in; always @(posedge clk) begin old_in <= in; anyedge <= (in & ~old_in) | (~in & old_in); end ``` https://hdlbits.01xz.net/wiki/Edgecapture | in | $\text{in}_\text{old}$ | $\text{out}_\text{old}$ | reset | out | |:---:|:----------------------:|:-----------------------:|:-----:|:---:| | 0 | 0 | 0 | 0 | 0 | | 0 | 0 | 1 | 0 | 1 | | 0 | 1 | 0 | 0 | 1 | | 0 | 1 | 1 | 0 | 1 | | 1 | 0 | 0 | 0 | 0 | | 1 | 0 | 1 | 0 | 1 | | 1 | 1 | 0 | 0 | 0 | | 1 | 1 | 1 | 0 | 1 | | x | x | x | 1 | 0 | | in | $\text{in}_\text{old}$ | out | reset | $\text{out}_\text{next}$ | |:---:|:----------------------:|:---:|:-----:|:------------------------:| | 0 | 0 | 0 | 0 | 0 | | 0 | 0 | 1 | 0 | 1 | | 0 | 1 | 0 | 0 | 1 | | 0 | 1 | 1 | 0 | 1 | | 1 | 0 | 0 | 0 | 0 | | 1 | 0 | 1 | 0 | 1 | | 1 | 1 | 0 | 0 | 0 | | 1 | 1 | 1 | 0 | 1 | | x | x | x | 1 | 0 | ### Product of Sum **Row 0** $\text{out}_\text{next} = (\text{in}) + (\text{in}_\text{old}) + (\text{out})$ **Row 4** $\text{out}_\text{next} = (\overline{\text{in}}) + (\text{in}_\text{old}) + (\text{out})$ **Row 6** $\text{out}_\text{next} = (\overline{\text{in}}) + (\overline{\text{in}_\text{old}}) + (\text{out})$ **Row 6** $\text{out}_\text{next} = (\overline{\text{reset}})$ :::spoiler Ans ```verilog reg [31:0] in_old; wire [31:0] out_next; assign out_next = (in | in_old | out) & (~in | in_old | out) & (~in | ~in_old | out) & {32{~reset}}; always @(posedge clk) begin old_in <= in; out <= out_next; end ``` :::spoiler ## https://hdlbits.01xz.net/wiki/Dualedge ### MY_ANS :::spoiler Ans ```verilog reg new_pos; reg new_neg; always @(posedge clk)begin new_pos <= d; end always @(negedge clk)begin new_neg <= d; end always @(*)begin case(clk) 1'b1: q = new_pos; 1'b0: q = new_neg; endcase end ``` ::: 原理上可行,但不推薦用 case(clk) combinational 判斷,因為 clk 是連續波形,可能造成 latch inference。 :::spoiler Ans ```verilog // A positive-edge triggered flip-flop always @(posedge clk) p <= d ^ n; // A negative-edge triggered flip-flop always @(negedge clk) n <= d ^ p; // Why does this work? // After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d. // After negedge clk, n changes to d^p. Thus q = (p^n) = (p^d^p) = d. // At each (positive or negative) clock edge, p and n FFs alternately // load a value that will cancel out the other and cause the new value of d to remain. assign q = p ^ n; ``` ::: 所以設計電路的時候要先從輸出去思考,都要從LHS 的角度去思考,這樣子才可以把時間因素一起考慮進去。 難怪大家都說寫Verilog 都要先思考Output 是什麼。 所以根據以上的推論試著把更新時間也考慮進去推導,從LHS 的角度去思考 1. 把需求拆成「每個 edge 要達到的 q 值」 posedge clk → 需要 q = d negedge clk → 需要 q = d 2. 分配兩個單邊 FF(p/n)分別捕捉正/負緣 posedge clk → 需要 p = d negedge clk → 需要 n = d 3. 想辦法讓每個 edge 更新能「抵消另一個 FF 的舊值」 4. XOR 是一個自然方法,因為 A ^ A = 0 , A is 0 or A is 1. q = (p) ^ (n) 是一個自然的方法 #### 先假設 posedge 去思考 p 就是new ,n 會變成 OLD,通常new 就不會寫,因為現在是posedge q = p ^ n_old 現在 p <= d,然後要把 n_old 消除的話就會是 n_old ^ n_old 先把q 假設出來 第一種假設 p <= d | n_old : q = d | n_old ^ n_old 第二種架設 p <= d ^ n_old : q = d ^ n_old ^ n_old 第二種假設 p <= d & n_old : q = d & n_old ^ n_old 目標truth table d(in) x_old(in) q(out) 0 0 0 只有第二種符合 0 1 0 都符合 1 0 1 都符合 1 1 1 都符合 #### 假設 negedge 去思考 也是只有第二種合理 n <= d ^ p_old : q = p_old ^ d ^ p_old #### 所以要在Always 當中都變成 :::spoiler Ans ```verilog // A positive-edge triggered flip-flop always @(posedge clk) p <= d ^ n; // A negative-edge triggered flip-flop always @(negedge clk) n <= d ^ p; ```` ::: ## https://hdlbits.01xz.net/wiki/Count_clock :::spoiler Ans ```verilog module bcd_counter( input clk, input reset, input ena, input [3:0] reset_value, input [3:0] max_value, output reg [3:0] bcd); always @(posedge clk) begin if (reset || (ena && (bcd == max_value))) begin bcd <= reset_value; end else if (ena) begin bcd <= bcd + 1'b1; end end endmodule module top_module( input clk, input reset, input ena, output reg pm, output [7:0] hh, output [7:0] mm, output [7:0] ss); // 秒 bcd_counter s1(clk, reset, ena, 4'd0, 4'd9, ss[3:0]); wire s2_ena = (ena && ss[3:0] == 4'd9); bcd_counter s2(clk, reset, s2_ena, 4'd0, 4'd5, ss[7:4]); // 分 wire m1_ena = (s2_ena && ss[7:4] == 4'd5); bcd_counter m1(clk, reset, m1_ena, 4'd0, 4'd9, mm[3:0]); wire m2_ena = (m1_ena && mm[3:0] == 4'd9); bcd_counter m2(clk, reset, m2_ena, 4'd0, 4'd5, mm[7:4]); // 小時:先處理個位數 wire h1_ena = (m2_ena && mm[7:4] == 4'd5); bcd_counter h1( clk, reset, h1_ena, (reset ? 2'd2 : (hh == 8'h12 ? 4'd1 : 4'd0)), // 如果是12,下一個小時要回 01 (hh[7:4] == 1 ? 4'd2 : 4'd9), // 如果是 1x,max=2,否則 max=9 hh[3:0] ); // 小時:十位數 (0~1) wire h2_ena = (h1_ena && ((hh[7:4] == 0 && hh[3:0] == 9) || (hh[7:4] == 1 && hh[3:0] == 2))); bcd_counter h2( clk, reset, h2_ena, (reset ? 1'd1 : (hh == 8'h12 ? 4'd0 : hh[7:4])), // 12 → 01 4'd1, hh[7:4] ); // AM/PM 切換 always @(posedge clk) begin if (reset) begin pm <= 0; // AM end else if (h1_ena && hh == 8'h11 && mm == 8'h59 && ss == 8'h59) begin pm <= ~pm; // 在 11:59:59 翻轉 end end endmodule ``` ::: ## https://hdlbits.01xz.net/wiki/Shift18 :::spoiler Ans ```verilog module top_module( input clk, input load, input ena, input [1:0] amount, input [63:0] data, output reg [63:0] q); always @(posedge clk) begin if(load) begin q <= data; end else if(ena) begin if (amount == 2'b00) begin //shift left by 1 bit. q[63:1] <= q[62:0]; q[0] <= 0; end else if (amount == 2'b01) begin //shift left by 8 bits. q[63:8] <= q[55:0]; q[7:0] <= 0; end else if (amount == 2'b10) begin //shift right by 1 bit. q[62:0] <= q[63:1]; end else if (amount == 2'b11) begin //shift right by 8 bits. // First Version // if(q[63] == 1'b1) begin // q[63:0] <= {{8{1'b1}}, q[63:8]}; // end // else begin // q[62:0] <= q[63:8]; // end // Second Version q[62:0] <= {{7{q[63]}}, q[63:8]}; end end end endmodule ``` ::: ## https://hdlbits.01xz.net/wiki/Shift18 :::spoiler Ans ```verilog module dff_module( input clk, input d, input reset, input reset_value, output q ); always @ (posedge clk) begin if(reset) begin q <= reset_value; end else begin q <= d; end end endmodule module top_module( input clk, input reset, // Active-high synchronous reset to 5'h1 output [4:0] q ); dff_module dff1(clk, q[1], reset, 1, q[0]); dff_module dff2(clk, q[2], reset, 0, q[1]); dff_module dff3(clk, q[3]^q[0], reset, 0, q[2]); dff_module dff4(clk, q[4], reset, 0, q[3]); dff_module dff5(clk, q[0], reset, 0, q[4]); endmodule ``` ::: ## https://hdlbits.01xz.net/wiki/Lfsr5 :::spoiler ANS1 直覺解法1 ```verilog module dff_module( input clk, input d, input reset, input reset_value, output q ); always @ (posedge clk) begin if(reset) begin q <= reset_value; end else begin q <= d; end end endmodule ``` ```verilog module top_module( input clk, input reset, // Active-high synchronous reset to 5'h1 output [4:0] q ); dff_module dff1(clk, q[1], reset, 1, q[0]); dff_module dff2(clk, q[2], reset, 0, q[1]); dff_module dff3(clk, q[3]^q[0], reset, 0, q[2]); dff_module dff4(clk, q[4], reset, 0, q[3]); dff_module dff5(clk, q[0], reset, 0, q[4]); endmodule ``` ::: :::spoiler 換成Vector 寫法 Step1 ```verilog dff_module dff1(clk, {q[2],q[1]}, reset, 2'b01, {q[1],q[0]}); dff_module dff3(clk, q[3]^q[0], reset, 0, q[2]); dff_module dff4(clk, {q[0], q[4]}, reset, 2'b00, {q[4], q[3]}); ``` 記得要把dff_module 改成5bit ```verilog module dff_module( input clk, input [4:0]d, input reset, input [4:0]reset_value, output [4:0]q ); always @ (posedge clk) begin if(reset) begin q <= reset_value; end else begin q <= d; end end endmodule module top_module( input clk, input reset, // Active-high synchronous reset to 5'h1 output [4:0] q ); wire [4:0] d = {q[0]^0, q[4]^0, (q[3]^q[0]), q[2]^0, q[1]^0}; dff_module dff1(clk, d, reset, 5'b00001, q[4:0]); endmodule ``` 可以把`wire [4:0] d`這一段在寫成更 Gernal 步驟如下 Step0 ```verilog wire [4:0] d = {q[0]^0, q[4]^0, (q[3]^q[0]), q[2]^0, q[1]^0}; ``` step1 ```verilog wire [4:0] d = {(q[0]^1'b0), (q[4]^1'b0), (q[3]^q[0]), (q[2]^1'b0), (q[1]^1'b0)}; ``` step2 ```verilog wire [4:0] d = {q[0], q[4], q[3], q[2], q[1]} ^ {1'b0, 1'b0, q[0], 1'b0, 1'b0}; ``` step3 ```verilog wire [4:0] d = {q[0], q[4:1]} ^ {1'b0, 1'b0, q[0], 1'b0, 1'b0}; ``` step4 > taps at bit positions **5** and **3**. (Tap positions are usually numbered starting from 1) ```verilog wire [4:0] d = {1'b0, q[4:1]} ^ {q[0], 1'b0, q[0], 1'b0, 1'b0}; // 5, 4, 3, 2, 1 ``` ::: ## https://hdlbits.01xz.net/wiki/Lfsr32 思考步驟是觀察Lfsr5 發現可以換成Vector 的方式實現,先回去實驗小題目的規則,這樣子必較好寫。 dff_module 就改成32 Bits的版本就可以了,上面的是5 Bits 版本 :::spoiler ANS1 ```verilog module top_module( input clk, input reset, // Active-high synchronous reset to 32'h1 output [31:0] q5 ); wire [31:0] d = {1'b0, q[31:1]} ^ {q[0], {9{1'b0}} , q[0], {18{1'b0}}, 1'b0, q[0], q[0]}; // 32, 23, 22, 21-4, 3, 2, 1 //taps at bit positions 32, 22, 2, and 1. dff_module dff1(clk, d, reset, 32'h1, q[31:0]); ``` ::: ## [m2014 q4k](https://hdlbits.01xz.net/wiki/Exams/m2014_q4k) :::spoiler ANS ```verilog module top_module ( input clk, input resetn, // synchronous reset input in, output out); reg [3:0] q; always @ (posedge clk) begin if(resetn == 1'b0) begin q <= 4'b0; end else begin q[3] <= in; q[2:0] <= q[3:1]; end end assign out = q[0]; endmodule ``` ::: ## [Exams/2014 q4b](https://hdlbits.01xz.net/wiki/Exams/2014_q4b) :::spoiler ANS ```verilog module top_module ( input [3:0] SW, input [3:0] KEY, output [3:0] LEDR ); // MUXDFF MUXDFF3(KEY[0],KEY[3],SW[3],KEY[1],KEY[2],LEDR[3]); MUXDFF MUXDFF2(KEY[0],LEDR[3],SW[2],KEY[1],KEY[2],LEDR[2]); MUXDFF MUXDFF1(KEY[0],LEDR[2],SW[1],KEY[1],KEY[2],LEDR[1]); MUXDFF MUXDFF0(KEY[0],LEDR[1],SW[0],KEY[1],KEY[2],LEDR[0]); endmodule module MUXDFF ( input clk, input w, R, E, L, output Q ); wire mux1, mux2; assign mux1 = E ? w : Q; assign mux2 = L ? R : mux1; always @(posedge clk)begin Q <= mux2; end endmodule ``` ::: ## https://hdlbits.01xz.net/wiki/Fsm3onehot What does "derive equations by inspection" mean? One-hot state machine encoding guarantees that exactly one state bit is 1. Although knowing this algorithm isn't necessary for RTL-level design (the logic synthesizer handles this), it is illustrative of why one-hot FSMs often have simpler logic (at the expense of more state bit storage), and this topic frequently shows up on exams in digital logic courses. ## [ece241_2013_q4](https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q4) | State | Next State | | | | Output | | | | | ----- | ---------- | ---- | ---- | ---- | ------ | --- | --- | --- | | | None=1 | S1=1 | S2=1 | S3=1 | FR1 | FR2 | FR3 | DFR | | None | None | S1 | S2 | S3 | 1 | 1 | 1 | 1 | | S1 | None | S1 | S2 | S3 | 1 | 1 | 0 | 0 | | S2 | None | S1_D | S2 | S3 | 1 | 0 | 0 | 0 | | S3 | None | S1_D | S2_D | S3 | 0 | 0 | 0 | 0 | | S2_D | None | S1_D | S2_D | S3 | 1 | 0 | 0 | 1 | | S1_D | None | S1_D | S2 | S3 | 1 | 1 | 0 | 1 | ``` // State transition logic // State flip-flops with synchronous reset // Output logic ``` :::spoiler ans ```verilog module top_module ( input clk, input reset, input [3:1] s, output fr3, output fr2, output fr1, output dfr ); parameter NONE=3'd0, S1=3'd1, S2=3'd2, S3=3'd3, S2_D=3'd4, S1_D=3'd5; reg [2:0] state, next_state; // State transition logic always @(*) begin case (state) default: next_state = 'x; //Synthesis Determine NONE: next_state = s[3] ? S3 : (s[2] ? S2 : (s[1] ? S1 : NONE)); S1 : next_state = s[3] ? S3 : (s[2] ? S2 : (s[1] ? S1 : NONE)); S2 : next_state = s[3] ? S3 : (s[2] ? S2 : (s[1] ? S1_D : NONE)); S3 : next_state = s[3] ? S3 : (s[2] ? S2_D : (s[1] ? S1_D : NONE)); S2_D: next_state = s[3] ? S3 : (s[2] ? S2_D : (s[1] ? S1_D : NONE)); S1_D: next_state = s[3] ? S3 : (s[2] ? S2 : (s[1] ? S1_D : NONE)); endcase end // State flip-flops with synchronous reset always @ (posedge clk) begin if(reset) begin state <= NONE; end else begin state <= next_state; end end // Output logic always @ (*) begin case (state) default: {fr3,fr2,fr1,dfr} = 'x; NONE : {fr3,fr2,fr1,dfr} = 4'b1111; S1 : {fr3,fr2,fr1,dfr} = 4'b0110; S2 : {fr3,fr2,fr1,dfr} = 4'b0010; S3 : {fr3,fr2,fr1,dfr} = 4'b0000; S2_D : {fr3,fr2,fr1,dfr} = 4'b0011; S1_D : {fr3,fr2,fr1,dfr} = 4'b0111; endcase end endmodule ``` ::: ## [Tb/clock](https://hdlbits.01xz.net/wiki/Tb/clock) :::spoiler ans ```verilog module top_module ( ); reg clk; // testbench clock dut uut ( // instance of dut .clk(clk) ); initial begin clk = 0; // initialize to zero forever #5 clk = ~clk; // toggle every 5 ps -> 10 ps period end endmodule ``` ::: ## [Tb/tb2](https://hdlbits.01xz.net/wiki/Tb/tb2) :::spoiler ans ```verilog module top_module(); reg clk, in, out; reg [2:0] s; q7 q7_inst(clk, in, s, out); initial begin clk = 0; forever #5 clk = ~clk; end initial begin in = 0; #20 in = 1; #10 in = 0; #10 in = 1; #30 in = 0; end initial begin s = 3'd2; #10 s = 3'd6; #10 s = 3'd2; #10 s = 3'd7; #10 s = 3'd0; end endmodule ``` ::: ## [Lemmings4](https://hdlbits.01xz.net/wiki/Lemmings4) :::spoiler ans ```verilog module top_module( input clk, input areset, // Freshly brainwashed Lemmings walk left. input bump_left, input bump_right, input ground, input dig, output walk_left, output walk_right, output aaah, output digging ); parameter LEFT=3'd0, RIGHT=3'd1, FALL_LEFT=3'd2, FALL_RIGHT=3'd3, DIG_L=3'd4, DIG_R=3'd5, SPLAT=3'd6; reg [2:0] state, next_state; reg [4:0] fall_cycles; always @(*) begin case (state) default : next_state = 'x; LEFT : next_state = ground ? (dig ? DIG_L : (bump_left ? RIGHT : LEFT)) : FALL_LEFT; RIGHT : next_state = ground ? (dig ? DIG_R : (bump_right ? LEFT : RIGHT)) : FALL_RIGHT; FALL_LEFT : next_state = ground ? ((fall_cycles == 5'd20) ? SPLAT : LEFT): FALL_LEFT; FALL_RIGHT : next_state = ground ? ((fall_cycles == 5'd20) ? SPLAT : RIGHT) : FALL_RIGHT; DIG_L : next_state = ground ? DIG_L : FALL_LEFT; DIG_R : next_state = ground ? DIG_R : FALL_RIGHT; SPLAT : next_state = SPLAT; endcase end always @(posedge clk, posedge areset) begin if(areset) begin state <= LEFT; end else begin state <= next_state; end end always @(posedge clk, posedge areset) begin if(areset) begin fall_cycles <= 0; end else if((state == FALL_LEFT) || (state == FALL_RIGHT))begin if(fall_cycles < 5'd20) begin fall_cycles <= fall_cycles + 1'd1; end end else begin fall_cycles <= 0; end end // Output logic assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); assign aaah = ((state == FALL_LEFT) || (state == FALL_RIGHT)); assign digging = (state == DIG_L) || (state == DIG_R); endmodule ``` ::: ## [Fsm serial](https://hdlbits.01xz.net/wiki/Fsm_serial) one start bit (0), 8 data bits, and 1 stop bit (1) 觀察發現Before Start Bit(0), 要先等到Stop bit(1) ```graphviz digraph FSM { rankdir=LR; node [shape = circle]; INIT [label="",shape=plaintext]; INIT -> START [label="reset"]; START -> DATA [label="in == 1"]; START -> START [label="in == 0"]; DATA -> STOP; DATA -> DATA [label="bits < 8"]; STOP -> DONE [label="in == 1"]; STOP -> WAIT [label="in == 0"]; WAIT -> START [label="in == 1"]; WAIT -> WAIT [label="in == 0"]; DONE -> DATA [label="in == 0"]; DONE -> START [label="in == 1"]; } ``` ::: spoiler ANS ```verilog module top_module( input clk, input in, input reset, // Synchronous reset output done ); parameter START=3'd0, DATA=3'd1, STOP=3'd2, DONE=3'd3, WAIT=3'd4; reg [2:0] state, count; wire [2:0] next_state; // State transition logic (combinational) always @ (*) begin case (state) START : next_state = (in == 0) ? DATA : START; DATA : next_state = (count == 7) ? STOP : DATA; STOP : next_state = (in == 1) ? DONE : WAIT; WAIT : next_state = (in == 0) ? WAIT : START; DONE : next_state = (in == 0) ? DATA : START; endcase end // State flip-flops (sequential) always @ (posedge clk) begin if(reset) begin state <= START; count <= 0; end else begin state <= next_state; if(state == DATA) begin count <= count + 1'd1; end else begin count <= 0; end end end // Output logic assign done = (state == DONE); endmodule ``` ::: ## [Fsm_serialdata](https://hdlbits.01xz.net/wiki/Fsm_serialdata) assign out_byte = data[0:7]; out_byte[7] 會對應到 data[0] out_byte[6] 會對應到 data[1] ... out_byte[0] 會對應到 data[7] :::spoiler ANS ```verilog module top_module( input clk, input in, input reset, // Synchronous reset output [7:0] out_byte, output done ); // parameter START=3'd0, DATA=3'd1, STOP=3'd2, DONE=3'd3, WAIT=3'd4; reg [2:0] state, count; wire [2:0] next_state; reg [0:7] data; // State transition logic (combinational) always @ (*) begin case (state) START : next_state = (in == 0) ? DATA : START; DATA : next_state = (count == 7) ? STOP : DATA; STOP : next_state = (in == 1) ? DONE : WAIT; WAIT : next_state = (in == 0) ? WAIT : START; DONE : next_state = (in == 0) ? DATA : START; endcase end // State flip-flops (sequential) always @ (posedge clk) begin if(reset) begin state <= START; count <= 0; end else begin state <= next_state; if(state == DATA) begin data[0:7] <= {in, data[0:6]}; count <= count + 1'd1; end else begin count <= 0; end end end // Output logic assign done = (state == DONE); // New: Datapath to latch input bits. assign out_byte = data[0:7]; endmodule ``` ::: ## [Fsm_serialdp](https://hdlbits.01xz.net/wiki/Fsm_serialdp) ```graphviz digraph FSM { rankdir=LR; node [shape = circle]; INIT [label="",shape=plaintext]; DATA [label="DATA"] INIT -> START [label="reset"]; START -> DATA [label="in == 1"]; START -> START [label="in == 0"]; DATA -> DATA [label="bits < 8"]; DATA -> ODD; ODD -> STOP; STOP -> DONE [label="in == 1"]; STOP -> WAIT [label="in == 0"]; WAIT -> START [label="in == 1"]; WAIT -> WAIT [label="in == 0"]; DONE -> DATA [label="in == 0"]; DONE -> START [label="in == 1"]; } ``` ```graphviz ``` ```verilog parity parity_inst(clk, parity_reset, parity_in, odd); ``` | STATE | parity_reset | parity_in | |:-----:|:------------:|:---------:| | START | 1 | 0 | | DATA | 0 | 1 | | ODD | 0 | 1 | | STOP | 0 | 0 | | WAIT | 0 | 0 | | DONE | 1 | 0 | :::spoiler ANS ```verilog module top_module( input clk, input in, input reset, // Synchronous reset output [7:0] out_byte, output done ); // parameter START=3'd0, DATA=3'd1, STOP=3'd2, DONE=3'd3, WAIT=3'd4; parameter ODD=3'd5; //NEW reg [2:0] state, count; wire [2:0] next_state; reg [0:7] data; // State transition logic (combinational) always @ (*) begin case (state) START : next_state = (in == 0) ? DATA : START; DATA : next_state = (count == 7) ? ODD : DATA; //NEW ODD : next_state = STOP; //NEW STOP : next_state = (in == 1) ? DONE : WAIT; WAIT : next_state = (in == 0) ? WAIT : START; DONE : next_state = (in == 0) ? DATA : START; endcase end // State flip-flops (sequential) always @ (posedge clk) begin if(reset) begin state <= START; count <= 0; end else begin state <= next_state; if(state == DATA) begin data[0:7] <= {in, data[0:6]}; count <= count + 1'd1; end else begin count <= 0; end end end assign out_byte = data[0:7]; // New: Add parity checking. wire parity_reset, parity_in, odd; parity parity_inst(clk, parity_reset, parity_in, odd); always @(*) begin case (state) START : begin parity_reset = 1; parity_in = 0 ; end //Done == START DATA : begin parity_reset = 0; parity_in = in; end ODD : begin parity_reset = 0; parity_in = in; end STOP : begin parity_reset = 0; parity_in = 0 ; end WAIT : begin parity_reset = 0; parity_in = 0 ; end DONE : begin parity_reset = 1; parity_in = 0 ; end //Done == START endcase end assign done = ((state == DONE) && (odd == 1'b1)); endmodule ``` ::: ## [Fsm_hdlc](https://hdlbits.01xz.net/wiki/Fsm_hdlc) :::spoiler ANS ```graphviz digraph FSM { rankdir=LR node [shape = circle] INIT [label="",shape=plaintext] INIT -> NONE [label="reset"] NONE -> NONE [label="0"] NONE -> ONE [label="1"] ONE -> NONE [label="0"] ONE -> TWO [label="1"] TWO -> THREE[label="1"] TWO -> NONE [label="0"] THREE-> FOUR [label="1"] THREE-> NONE [label="0"] FOUR -> FIVE [label="1"] FOUR -> NONE [label="0"] FIVE -> DISC [label="0"] FIVE -> SIX [label="1"] DISC -> NONE [label="0"] DISC -> ONE [label="1"] SIX -> ERR [label="1"] SIX -> FLAG [label="0"] FLAG -> NONE [label="0"] FLAG -> ONE [label="1"] ERR -> NONE [label="0"] ERR -> ERR [label="1"] } ``` :::spoiler ## [ece241_2013_q8](https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q8) Mealy-type finite state machine ```graphviz digraph FSM { rankdir=LR; node [shape = circle]; // States S0 [label="S0\n(no history)"]; S1 [label="S1\n(seen '1')"]; S2 [label="S2\n(seen '10')"]; // Transitions S0 -> S1 [label="x=1 / z=0"]; S0 -> S0 [label="x=0 / z=0"]; S1 -> S1 [label="x=1 / z=0"]; S1 -> S2 [label="x=0 / z=0"]; S2 -> S1 [label="x=1 / z=1"]; // detection here S2 -> S0 [label="x=0 / z=0"]; // Initial state INIT [shape=plaintext, label="reset"]; INIT -> S0; } ```