# 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;
}
```