HDLbits 解題筆記 (持續更新中...)
================================================================
作者:朱品為 Will Chu
目的:純粹分享自己在寫HDLbits的解題記錄,思路,若有更好的解法歡迎留言!
**Getting Started 以及 Verilog Language 章節 太基礎我就沒把答案放上來了需要的可以mail我。**
email: will19981217@gmail.com
* @@ --> 做很多次沒成功,參考了詳解。
* V --> 完全自己寫完
* 題目中間有提到的一些知識點,我會直接添加在解題思路中做更深入介紹。
* VScode關掉Copilot提示 --> [Link](https://blog.csdn.net/Mr_Wuuuuuu/article/details/135903835)
# Combinational Logic
## Basic Gates
## Multiplexers
## Arithmetic Circuit
## Karnaugh Map to Circuit
### 3-variable (Kmap1)
>Implement the circuit described by the Karnaugh map below.
>
>Try to simplify the k-map before coding it. Try both product-of-sums and sum-of-products forms. We can't check whether you have the optimal simplification of the k-map. But we can check if your reduction is equivalent, and we can check whether you can translate a k-map into a circuit.
```verilog=
module top_module(
input a,
input b,
input c,
output out );
assign out = a | b | c;
endmodule
```
------------------------------------------------------------
### 4-variable (Kmap2)
>Implement the circuit described by the Karnaugh map below.
>
>Try to simplify the k-map before coding it. Try both product-of-sums and sum-of-products forms. We can't check whether you have the optimal simplification of the k-map. But we can check if your reduction is equivalent, and we can check whether you can translate a k-map into a circuit.
```verilog=
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = ~c & ~b | ~c & ~d & ~a | c & ~d & ~a | c & d & b | c & d & a;
endmodule
```
------------------------------------------------------------------
### 4-vairable (Kmap3)
>Implement the circuit described by the Karnaugh map below.
>
>Try to simplify the k-map before coding it. Try both product-of-sums and sum-of-products forms. We can't check whether you have the optimal simplification of the k-map. But we can check if your reduction is equivalent, and we can check whether you can translate a k-map into a circuit.
```verilog=
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = a | (~a) & (~b) & c;
endmodule
```
--------------------------------------------------------------
### 4-variable (Kmap4)
>Implement the circuit described by the Karnaugh map below.
>
>Try to simplify the k-map before coding it. ~~Try both product-of-sums and sum-of-products forms~~. We can't check whether you have the optimal simplification of the k-map. But we can check if your reduction is equivalent, and we can check whether you can translate a k-map into a circuit.
```verilog=
module top_module(
input a,
input b,
input c,
input d,
output out );
assign out = a ^ b ^ c ^ d;
endmodule
```
---------------------------------------------------------------------
### Minimum SOP and POS (Exams/ece241 2013 q2)
>A single-output digital system with four inputs (a,b,c,d) generates a logic-1 when 2, 7, or 15 appears on the inputs, and a logic-0 when 0, 1, 4, 5, 6, 9, 10, 13, or 14 appears. The input conditions for the numbers 3, 8, 11, and 12 never occur in this system. For example, 7 corresponds to a,b,c,d being set to 0,1,1,1, respectively.
>
>Determine the output out_sop in minimum SOP form, and the output out_pos in minimum POS form.
```verilog=
module top_module (
input a,
input b,
input c,
input d,
output out_sop,
output out_pos
);
assign out_sop = (~a&~b&c) | (c&d);
assign out_pos = c & (~a|d) & (~b|d);
endmodule
```
------------------------------------------------------------------
### Karnaugh mao (Exams/m2014 q3)
>Consider the function f shown in the Karnaugh map below.
>
>Implement this function. **d** is don't-care, which means you may choose to output whatever value is convenient.
```verilog=
module top_module (
input [4:1] x,
output f );
assign f = (~x[1] & x[3]) || (x[2] & x[4]);
endmodule
```
------------------------------------------------------------------
### Karnaugh map (Exams/2012 q1g)
>Consider the function f shown in the Karnaugh map below. Implement this function.
>(The original exam question asked for simplified SOP and POS forms of the function.)
>
```verilog=
module top_module (
input [4:1] x,
output f
);
assign f = (~x[2] & ~x[4]) | (~x[1] & x[3]) | (x[2] & x[3] & x[4]);
endmodule
```
-----------------------------------------------------------------------
### K-map implemented with a multiplexer (Exams/ece241 2014 q3)
>For the following Karnaugh map, give the circuit implementation using one 4-to-1 multiplexer and as many 2-to-1 multiplexers as required, but using as few as possible. You are not allowed to use any other logic gate and you must use a and b as the multiplexer selector inputs, as shown on the 4-to-1 multiplexer below.
>
>You are implementing just the portion labelled top_module, such that the entire circuit (including the 4-to-1 mux) implements the K-map.
>
>
>(The requirement to use only 2-to-1 multiplexers exists because the original exam question also wanted to test logic function simplification using K-maps and how to synthesize logic functions using only multiplexers. If you wish to treat this as purely a Verilog exercise, you may ignore this constraint and write the module any way you wish.)
```verilog=
module top_module (
input c,
input d,
output [3:0] mux_in
);
assign mux_in[0] = c ? 1'b1 : d;
assign mux_in[1] = 1'b0;
assign mux_in[2] = d ? 1'b0 : 1'b1;
assign mux_in[3] = c ? d : 1'b0;
/*
//second way
assign mux_in[0] = c | d;
assign mux_in[1] = 1'b0;
assign mux_in[2] = ~d;
assign mux_in[3] = c & d;
*/
endmodule
```
-------------------------------------------------------------------
# Sequential Logic
## Latches and Filp-Flops
### D flip-flop (Dff)
>A D flip-flop is a circuit that stores a bit and is updated periodically, at the (usually) positive edge of a clock signal.
>
>D flip-flops are created by the logic synthesizer when a clocked always block is used (See alwaysblock2). A D flip-flop is the simplest form of "blob of combinational logic followed by a flip-flop" where the combinational logic portion is just a wire.
>
>Create a single D flip-flop.
```verilog=
module top_module (
input clk, // Clocks are used in sequential circuits
input d,
output reg q );//
always@(posedge clk)begin
q <= d;
end
// Use a clocked always block
// copy d to q at every positive edge of clk
// Clocked always blocks should use non-blocking assignments
endmodule
```
---------------------------------------------------------------------
### D flip-flops (Dff8)
>Create 8 D flip-flops. All DFFs should be triggered by the positive edge of clk.
```verilog=
module top_module (
input clk,
input [7:0] d,
output [7:0] q
);
always@(posedge clk)begin
q <= d;
end
endmodule
```
---------------------------------------------------------------------
### DFF with reset (Dff8r)
>Create 8 D flip-flops with active high synchronous reset. All DFFs should be triggered by the positive edge of clk.
```verilog=
module top_module (
input clk,
input reset, // Synchronous reset
input [7:0] d,
output [7:0] q
);
always@(posedge clk)begin
if(reset)begin
q <= 0;
end else q = d;
end
endmodule
```
--------------------------------------------------------------------
### DFF with reset value (Dff8p)
>Create 8 D flip-flops with active high synchronous reset. The flip-flops must be reset to 0x34 rather than zero. All DFFs should be triggered by the negative edge of clk.
```verilog=
module top_module (
input clk,
input reset,
input [7:0] d,
output [7:0] q
);
always @(negedge clk)begin
if (reset == 1 )begin
q <= 8'h0x34;
end else q <= d;
end
endmodule
```
-------------------------------------------------------------------
### DFF with asynchronous reset (Dff8ar)
>Create 8 D flip-flops with active high asynchronous reset. All DFFs should be triggered by the positive edge of clk.
```verilog=
module top_module (
input clk,
input areset, // active high asynchronous reset
input [7:0] d,
output [7:0] q
);
always@(posedge clk or posedge areset)begin
if(areset)begin
q <= 0;
end else begin
q <= d;
end
end
endmodule
```
-------------------------------------------------------------------
### DFF with byte enable (Dff16e)
>Create 16 D flip-flops. It's sometimes useful to only modify parts of a group of flip-flops. The byte-enable inputs control whether each byte of the 16 registers should be written to on that cycle. byteena[1] controls the upper byte d[15:8], while byteena[0] controls the lower byte d[7:0].
>
>resetn is a synchronous, active-low reset.
>
>All DFFs should be triggered by the positive edge of clk.
```verilog=
module top_module (
input clk,
input resetn,
input [1:0] byteena,
input [15:0] d,
output [15:0] q
);
always@(posedge clk)begin
if(!resetn)begin
q <= 0;
end else begin
if(byteena[1] == 1 )
q[15:0] <= d[15:0];
else
q[15:8] <= q[15:8];
if(byteena[0] == 1)
q[7:0] <= d[7:0];
else
q[7:0] <= q[7:0];
end
end
endmodule
```
-------------------------------------------------------------------
### D Latch (Exams/m2014 q4a)
>Implement the following circuit:
>
>Note that this is a latch, so a Quartus warning about having inferred a latch is expected.
```verilog=
module top_module (
input d,
input ena,
output q);
always@(*)begin
if(ena) q = d;
end
endmodule
```
--------------------------------------------------------------------
### DFF (Exams/m2014 q4b)
>Implement the following circuit:
>
```verilog=
module top_module (
input clk,
input d,
input ar, // asynchronous reset
output q);
always@(posedge clk or posedge ar)begin
if(ar)
q <= 1'b0;
else
q <= d;
end
endmodule
```
-------------------------------------------------------------------
### DFF (Exams/m2014 q4c)
>Implement the following circuit:
>
```verilog=
module top_module (
input clk,
input d,
input r, // synchronous reset
output q);
always@(posedge clk)begin
if(r)
q <= 1'b0;
else
q <= d;
end
endmodule
```
-------------------------------------------------------------------
### DFF+gate (Exmas/m2014 q4d)
>Implement the following circuit:
>
```verilog=
module top_module (
input clk,
input in,
output out);
always@(posedge clk)begin
out <= out ^ in;
end
endmodule
```
-------------------------------------------------------------------
### Mux and DFF (Mt2015 muxdff)
>Taken from ECE253 2015 midterm question 5
>
>Consider the sequential circuit below:
>
>Assume that you want to implement hierarchical Verilog code for this circuit, using three instantiations of a submodule that has a flip-flop and multiplexer in it. Write a Verilog module (containing one flip-flop and multiplexer) named top_module for this submodule.
```verilog=
module top_module (
input clk,
input L,
input r_in,
input q_in,
output reg Q);
always@(posedge clk)begin
Q <= L?r_in:q_in;
end
endmodule
```
---------------------------------------------------------------------
### Mux and DFF (Exams/2014 q4a)
>Consider the n-bit shift register circuit shown below:
>
>Write a Verilog module named top_module for one stage of this circuit, including both the flip-flop and multiplexers.
```verilog=
module top_module (
input clk,
input w, R, E, L,
output Q
);
always@(posedge clk)begin
case({E,L})
2'b00 : Q <= Q;
2'b01 : Q <= R;
2'b10 : Q <= w;
2'b11 : Q <= R;
endcase
end
endmodule
```
----------------------------------------------------------------------
### DFFs and gates (Exams/ece241 2014 q4)
>Given the finite state machine circuit as shown, assume that the D flip-flops are initially reset to zero before the machine begins.
>
>Build this circuit.
>
```verilog=
module top_module (
input clk,
input x,
output z
);
reg [2:0] D;
always@(posedge clk)begin
D[0] <= (x ^ D[0]);
D[1] <= (x & (~D[1]));
D[2] <= (x | ~D[2]);
end
//assign z = ~(D[0] | D[1] | D[2]);
assign z = ~|D;
endmodule
```
----------------------------------------------------------------------
### Create circuit from truth table JK dff (Exams/ece241 2013 q7)
>A JK flip-flop has the below truth table. Implement a JK flip-flop with only a D-type flip-flop and gates. Note: Qold is the output of the D flip-flop before the positive clock edge.
>
```verilog=
module top_module (
input clk,
input j,
input k,
output Q);
always@(posedge clk)begin
case({j,k})
2'b00 : Q <= Q;
2'b01 : Q <= 0;
2'b10 : Q <= 1;
2'b11 : Q <= !Q;
endcase
end
endmodule
```
----------------------------------------------------------------------
### Detect an edge (Edgedetect)
>For each bit in an 8-bit vector, detect when the input signal changes from 0 in one clock cycle to 1 the next (similar to positive edge detection). The output bit should be set the cycle after a 0 to 1 transition occurs.
>
>Here are some examples. For clarity, in[1] and pedge[1] are shown separately.
>
```verilog=
module top_module (
input clk,
input [7:0] in,
output reg[7:0] pedge
);
reg [7:0] temp_in;
always@(posedge clk)begin
temp_in <= in;
pedge <= ~temp_in & in;
end
endmodule
```
----------------------------------------------------------------------
### Detect both edges (edgedetect2)
>For each bit in an 8-bit vector, detect when the input signal changes from one clock cycle to the next (detect any edge). The output bit should be set the cycle after a 0 to 1 transition occurs.
>
>Here are some examples. For clarity, in[1] and anyedge[1] are shown separately
>
```verilog=
module top_module (
input clk,
input [7:0] in,
output [7:0] anyedge
);
reg [7:0] tmp;
always@(posedge clk)begin
tmp <= in;
anyedge = tmp ^ in;
end
endmodule
```
--------------------------------------------------------------------
### Edge capture register (Edgecapture)
>For each bit in a 32-bit vector, capture when the input signal changes from 1 in one clock cycle to 0 the next. "Capture" means that the output will remain 1 until the register is reset (synchronous reset).
>
>Each output bit behaves like a SR flip-flop: The output bit should be set (to 1) the cycle after a 1 to 0 transition occurs. The output bit should be reset (to 0) at the positive clock edge when reset is high. If both of the above events occur at the same time, reset has precedence. In the last 4 cycles of the example waveform below, the 'reset' event occurs one cycle earlier than the 'set' event, so there is no conflict here.
>
>In the example waveform below, reset, in[1] and out[1] are shown again separately for clarity.
>
```verilog=
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] tmp;
integer i;
always@(posedge clk)begin
tmp <= in;
for(i=0; i<32;i++)begin
case({~in[i] & tmp[i],reset})
2'b10 : out[i] <= 1'b1; //only negedge
2'b11 : out[i] <= 1'b0; //negedge and reset
2'b01 : out[i] <= 1'b0; //only reset
default : out[i] <= out[i];
endcase
end
end
endmodule
```
---------------------------------------------------------------------
### Dual-edge triggered flip-flop (Dualedge)
>You're familiar with flip-flops that are triggered on the positive edge of the clock, or negative edge of the clock. A dual-edge triggered flip-flop is triggered on both edges of the clock. However, FPGAs don't have dual-edge triggered flip-flops, and always @(posedge clk or negedge clk) is not accepted as a legal sensitivity list.
>
>Build a circuit that functionally behaves like a dual-edge triggered flip-flop:
>
>(Note: It's not necessarily perfectly equivalent: The output of flip-flops have no glitches, but a larger combinational circuit that emulates this behaviour might. But we'll ignore this detail here.)
```verilog=
module top_module (
input clk,
input d,
output q
);
reg q1,q2;
always@(posedge clk)begin
q1 <= d ^ q2;
end
always@(negedge clk)begin
q2 <= d ^ q1;
end
assign q = q1 ^ q2;
endmodule
```
-------------------------------------------------------------------
## Countters
## Shift Registers
### 4-bit shift register (Shift 4)
>Build a 4-bit shift register (right shift), with asynchronous reset, synchronous load, and enable.
>
>* areset: Resets shift register to zero.
>* load: Loads shift register with data[3:0] instead of shifting.
>* ena: Shift right (q[3] becomes zero, q[0] is shifted out and disappears).
>* q: The contents of the shift register.
>If both the load and ena inputs are asserted (1), the load input has higher priority.
```verilog=
module top_module(
input clk,
input areset, // async active-high reset to zero
input load,
input ena,
input [3:0] data,
output reg [3:0] q);
always@(posedge clk or posedge areset)begin
if(areset) q <= 3'b000;
else begin
if(load)
q <= data;
else if(ena)
q <= {1'b0,q[3:1]};
end
end
endmodule
```
---------
### Left/right rotator (Rotate 100)
>Build a 100-bit left/right rotator, with synchronous load and left/right enable. A rotator shifts-in the shifted-out bit from the other end of the register, unlike a shifter that discards the shifted-out bit and shifts in a zero. If enabled, a rotator rotates the bits around and does not modify/discard them.
>
>* load: Loads shift register with data[99:0] instead of rotating.
>* ena[1:0]: Chooses whether and which direction to rotate.
>* * 2'b01 rotates right by one bit
>* * 2'b10 rotates left by one bit
>* * 2'b00 and 2'b11 do not rotate.
>* q: The contents of the rotator.
```verilog=
module top_module(
input clk,
input load,
input [1:0] ena,
input [99:0] data,
output reg [99:0] q);
always @(posedge clk) begin
if(load)begin
q <= data; // output already is a reg
end
else begin
case (ena)
2'b01: begin // right rotate
q <= {q[0],q[99:1]};
end
2'b10 : begin // left rotate
q <= {q[98:0],q[99]};
end
default: begin
q <= q;
end
endcase
end
end
endmodule
```
-------------------------------------------------------------------
### Shift register (Exams/2014 q4b)
>Consider the n-bit shift register circuit shown below:
>
>Write a top-level Verilog module (named top_module) for the shift register, assuming that n = 4. Instantiate four copies of your MUXDFF subcircuit in your top-level module. Assume that you are going to implement the circuit on the DE2 board.
>
>* Connect the R inputs to the SW switches,
>* clk to KEY[0],
>* E to KEY[1],
>* L to KEY[2], and
>* w to KEY[3].
>* Connect the outputs to the red lights LEDR[3:0].
>(Reuse your MUXDFF from exams/2014_q4a.)
```verilog=
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
); //
wire [3:0] Q;
MUXDFF M0 (.clk(KEY[0]), .w(Q[1]), .R(SW[0]), .E(KEY[1]), .L(KEY[2]), .Q(Q[0]));
MUXDFF M1 (.clk(KEY[0]), .w(Q[2]), .R(SW[1]), .E(KEY[1]), .L(KEY[2]), .Q(Q[1]));
MUXDFF M2 (.clk(KEY[0]), .w(Q[3]), .R(SW[2]), .E(KEY[1]), .L(KEY[2]), .Q(Q[2]));
MUXDFF M3 (.clk(KEY[0]), .w(KEY[3]), .R(SW[3]), .E(KEY[1]), .L(KEY[2]), .Q(Q[3]));
assign LEDR = Q;
endmodule
module MUXDFF (
input clk,
input w, R, E, L,
output Q
);
always@(posedge clk)begin
case({E,L})
2'b00 : Q <= Q;
2'b01 : Q <= R;
2'b10 : Q <= w;https://hackmd.io/meMuii0mQJSj5ssHgosQnw?both#
2'b11 : Q <= R;
endcase
end
endmodule
```
---------------------------------------------------------------------
### 3-input LUT (Exams/ece241 2013 q2)
>In this question, you will design a circuit for an 8x1 memory, where writing to the memory is accomplished by shifting-in bits, and reading is "random access", as in a typical RAM. You will then use the circuit to realize a 3-input logic function.
>
>First, create an 8-bit shift register with 8 D-type flip-flops. Label the flip-flop outputs from Q[0]...Q[7]. The shift register input should be called S, which feeds the input of Q[0] (MSB is shifted in first). The enable input controls whether to shift. Then, extend the circuit to have 3 additional inputs A,B,C and an output Z. The circuit's behaviour should be as follows: when ABC is 000, Z=Q[0], when ABC is 001, Z=Q[1], and so on. Your circuit should contain ONLY the 8-bit shift register, and multiplexers. (Aside: this circuit is called a 3-input look-up-table (LUT)).
```verilog=
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );
//8-bit shifter
reg [7:0] shifter;
always@(posedge clk)begin
if(enable) shifter <= {shifter[6:0], S};
else shifter <= shifter;
end
always@(*)begin
case({A, B, C})
3'b000: Z = shifter[0];
3'b001: Z = shifter[1];
3'b010: Z = shifter[2];
3'b011: Z = shifter[3];
3'b100: Z = shifter[4];
3'b101: Z = shifter[5];
3'b110: Z = shifter[6];
3'b111: Z = shifter[7];
endcase
end
endmodule
```
解題思路:這一題很有趣,用register加mux來做出LUT,n輸入的LUT就用2的n次方x1的register來完成。
-----------------------------------------------------------------
## More Circuit
### Rule 90
>Rule 90 is a one-dimensional cellular automaton with interesting properties.
>
>The rules are simple. There is a one-dimensional array of cells (on or off). At each time step, the next state of each cell is the XOR of the cell's two current neighbours. A more verbose way of expressing this rule is the following table, where a cell's next state is a function of itself and its two neighbours:
>
>(The name "Rule 90" comes from reading the "next state" column: 01011010 is decimal 90.)
>
>In this circuit, create a 512-cell system (q[511:0]), and advance by one time step each clock cycle. The load input indicates the state of the system should be loaded with data[511:0]. Assume the boundaries (q[-1] and q[512]) are both zero (off).
```verilog=
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q );
always@(posedge clk) begin
if(load)
q <= data;
else
q <= {1'b0,q[511:1]} ^ {q[510:0],1'b0};
end
endmodule
```
-----------------------------------------------------
### Rule 110
>Rule 110 is a one-dimensional cellular automaton with interesting properties (such as being Turing-complete).
>
>There is a one-dimensional array of cells (on or off). At each time step, the state of each cell changes. In Rule 110, the next state of each cell depends only on itself and its two neighbours, according to the following table:
>
>(The name "Rule 110" comes from reading the "next state" column: 01101110 is decimal 110.)
>
>In this circuit, create a 512-cell system (q[511:0]), and advance by one time step each clock cycle. The load input indicates the state of the system should be loaded with data[511:0]. Assume the boundaries (q[-1] and q[512]) are both zero (off).
```verilog=
module top_module(
input clk,
input load,
input [511:0] data,
output [511:0] q
);
//Draw K-map to figure out your output logic
always @(posedge clk) begin
if (load) begin
q <= data;
end
else begin
// Center = q, Right = {q[510:0], 1'b0}, Left = {1'b0, q[511:1]}
q <= ~q & {q[510:0], 1'b0} | ~{1'b0, q[511:1]} & q | q & ~{q[510:0], 1'b0};
end
end
endmodule
```
--------
## Finite State Machines
### Design a Moore FSM (@@)
>
>Also include an active-high synchronous reset that resets the state machine to a state equivalent to if the water level had been low for a long time (no sensors asserted, and all four outputs asserted).
```verilog=
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
// A -> below S1, B -> between S1,S2
// C -> between S2,S3 D -> above S3
parameter [1:0] A = 2'b00, B = 2'b01, C = 2'b10, D = 2'b11;
reg [1:0] cs, ns;
always@(posedge clk)begin
if(reset)begin
cs <= A;
end else begin
cs <= ns;
end
end
always@ (s)begin
case(s)
3'b000: begin
ns = A;
end
3'b001: begin
ns = B;
end
3'b011: begin
ns = C;
end
3'b111: begin
ns = D;
end
default: ns = 'x;
endcase
end
always@ (posedge clk)begin
if(reset)begin
fr3 <= 1'b1;
fr2 <= 1'b1;
fr1 <= 1'b1;
dfr <= 1'b1;
end else begin
case(ns)
A: begin
fr3 <= 1'b1;
fr2 <= 1'b1;
fr1 <= 1'b1;
dfr <= 1'b1;
end
B: begin
if(cs == A)begin
fr1 <= 1'b1;
fr2 <= 1'b1;
fr3 <= 1'b0;
dfr <= 1'b0;
end
else if (cs == B)begin
dfr <= dfr;
fr1 <= fr1;
fr2 <= fr2;
fr3 <= fr3;
end
else begin
dfr <= 1'b1;
fr1 <= 1'b1;
fr2 <= 1'b1;
fr3 <= 1'b0;
end
end
C: begin
if(cs == A || cs == B)begin
fr1 <= 1'b1;
fr2 <= 1'b0;
fr3 <= 1'b0;
dfr <= 1'b0;
end
else if (cs == C)begin
dfr <= dfr;
fr1 <= fr1;
fr2 <= fr2;
fr3 <= fr3;
end
else begin
dfr <= 1'b1;
fr1 <= 1'b1;
fr2 <= 1'b0;
fr3 <= 1'b0;
end
end
D: begin
fr1 <= 1'b0;
fr2 <= 1'b0;
fr3 <= 1'b0;
dfr <= 1'b0;
end
endcase
end
end
endmodule
```
------
### Lemmings 1 (V)
>The game Lemmings involves critters with fairly simple brains. So simple that we are going to model it using a finite state machine.
>
>In the Lemmings' 2D world, Lemmings can be in one of two states: walking left or walking right. It will switch directions if it hits an obstacle. In particular, if a Lemming is bumped on the left, it will walk right. If it's bumped on the right, it will walk left. If it's bumped on both sides at the same time, it will still switch directions.
>
>Implement a Moore state machine with two states, two inputs, and one output that models this behaviour.
>
>
```verilog=
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right); //
// parameter LEFT=0, RIGHT=1, ...
reg state, next_state;
always @(*) begin
// State transition logic
end
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
end
// Output logic
// assign walk_left = (state == ...);
// assign walk_right = (state == ...);
endmodule
```
------------
### Lemmings 2 (V)
```verilog=
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
// Parameter states
// A = walking left ; B = walking right ; C = falling left ; D = falling right
parameter A = 2'b00, B = 2'b01, C = 2'b10, D = 2'b11;
reg [1:0] cs, ns;
// current state register
always @(posedge clk or posedge areset) begin
if(areset) cs <= A;
else cs <= ns;
end
// next state state circuit
always @(*) begin
case (cs)
A: begin
if(ground == 'b0) ns = C;
else if(bump_left =='b1) ns = B;
else ns = cs;
end
B: begin
if(ground == 'b0) ns = D;
else if(bump_right =='b1) ns = A;
else ns = cs;
end
C: begin
if(ground == 1'b1) ns = A;
else ns = cs;
end
D: begin
if(ground == 1'b1) ns = B;
else ns = cs;
end
default: ns = A;
endcase
end
// Output logic FIRST way ----> Sequencial Logic USING DFF can avoid glitch
/*
always @(posedge clk or posedge areset) begin
if(areset)begin
walk_left = 'b1;
walk_right = 'b0;
aaah = 'b0;
end
else begin
case(ns)
A: begin
walk_left = 'b1;
walk_right = 'b0;
aaah = 'b0;
end
B: begin
walk_left = 'b0;
walk_right = 'b1;
aaah = 'b0;
end
C: begin
walk_left = 'b0;
walk_right = 'b0;
aaah = 'b1;
end
D: begin
walk_left = 'b0;
walk_right = 'b0;
aaah = 'b1;
end
endcase
end
end
*/
// Output Second way ----> Combinational Logic
assign walk_left = (cs == A);
assign walk_right = (cs == B);
assign aaah = (cs == C || cs == D);
endmodule
```
-----
### Lemmings 3 (V)
```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 states
// A = walking left; B = walking right; C = falling left;
// D = falling right; E = digging left; F = digging right
parameter A = 3'd1, B = 3'd2, C = 3'd3, D = 3'd4, E = 3'd5, F = 3'd6;
reg [2:0] cs, ns;
// current state register
always @(posedge clk or posedge areset) begin
if(areset) cs <= A;
else cs <= ns;
end
// next state state circuit
always @(*) begin
case (cs)
A: begin
if(ground == 'b0) ns = C;
else if (dig == 'b1) ns = E;
else if(bump_left =='b1) ns = B;
else ns = cs;
end
B: begin
if(ground == 'b0) ns = D;
else if (dig == 'b1) ns = F;
else if(bump_right =='b1) ns = A;
else ns = cs;
end
C: begin
if(ground == 'b1) ns = A;
else ns = cs;
end
D: begin
if(ground == 'b1) ns = B;
else ns = cs;
end
E: begin
if(ground == 'b0) ns = C;
else ns = cs;
end
F: begin
if(ground == 'b0) ns = D;
else ns = cs;
end
default: ns = A;
endcase
end
// Output logic FIRST way ----> Sequencial Logic USING DFF can avoid glitch
always @(posedge clk or posedge areset) begin
if(areset)begin
walk_left = 'b1;
walk_right = 'b0;
aaah = 'b0;
digging = 'b0;
end
else begin
case(ns)
A: begin
walk_left = 'b1;
walk_right = 'b0;
aaah = 'b0;
digging = 'b0;
end
B: begin
walk_left = 'b0;
walk_right = 'b1;
aaah = 'b0;
digging = 'b0;
end
C: begin
walk_left = 'b0;
walk_right = 'b0;
aaah = 'b1;
digging = 'b0;
end
D: begin
walk_left = 'b0;
walk_right = 'b0;
aaah = 'b1;
digging = 'b0;
end
E: begin
walk_left = 'b0;
walk_right = 'b0;
aaah = 'b0;
digging = 'b1;
end
F: begin
walk_left = 'b0;
walk_right = 'b0;
aaah = 'b0;
digging = 'b1;
end
endcase
end
end
// Output Second way ----> Combinational Logic
/*
assign walk_left = (cs == A);
assign walk_right = (cs == B);
assign aaah = (cs == C || cs == D);
assign digging = (cs == E || cs == F);
*/
endmodule
```
解題思路: 這一題沒什麼困難的就根據前面的2,1小題,加上一些動作即可。
詳情看code。
--------
### Lemmings 4 (@@)
```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 states
// A = walking left; B = walking right; C = falling left;
// D = falling right; E = digging left; F = digging right;
// G = splatter; H = ahhh end;
parameter A = 3'd0, B = 3'd1, C = 3'd2, D = 3'd3, E = 3'd4, F = 3'd5, G = 3'd6, H = 3'd7;
reg [2:0] cs, ns;
reg [4:0] cnt = 5'd0; //counter
// current state register
always @(posedge clk or posedge areset) begin
if(areset) cs <= A;
else cs <= ns;
end
// Counter
always @(posedge clk or posedge areset) begin
if(areset) cnt <= 'b0;
else if(ns == C || ns == D)cnt <= cnt + 1'b1;
else cnt <= 'b0;
end
// next state state circuit
always @(*) begin
case (cs)
A: begin
if(ground == 'b0) ns = C;
else if (dig == 'b1) ns = E;
else if(bump_left =='b1) ns = B;
else ns = cs;
end
B: begin
if(ground == 'b0) ns = D;
else if (dig == 'b1) ns = F;
else if(bump_right =='b1) ns = A;
else ns = cs;
end
C: begin
if(ground == 'b1) ns = A;
else begin
if(cnt == 5'd20) ns = G;
else ns = C;
end
end
D: begin
if(ground == 'b1) ns = B;
else begin
if(cnt == 5'd20) ns = G;
else ns = D;
end
end
E: begin
if(ground == 'b0) ns = C;
else ns = cs;
end
F: begin
if(ground == 'b0) ns = D;
else ns = cs;
end
G: begin // spalter
if(ground == 'b0) ns = G;
else ns = H;
end
H: begin // aaah end
ns = H;
end
default: begin
ns = A;
end
endcase
end
// Output logic FIRST way ----> Sequencial Logic USING DFF can avoid glitch
always @(posedge clk or posedge areset) begin
if(areset)begin
walk_left <= 'b1;
walk_right <= 'b0;
aaah <= 'b0;
digging <= 'b0;
end
else begin
case(ns)
A: begin
walk_left <= 'b1;
walk_right <= 'b0;
aaah <= 'b0;
digging <= 'b0;
end
B: begin
walk_left <= 'b0;
walk_right <= 'b1;
aaah <= 'b0;
digging <= 'b0;
end
C: begin
walk_left <= 'b0;
walk_right <= 'b0;
aaah <= 'b1;
digging <= 'b0;
end
D: begin
walk_left <= 'b0;
walk_right <= 'b0;
aaah <= 'b1;
digging <= 'b0;
end
E: begin
walk_left <= 'b0;
walk_right <= 'b0;
aaah <= 'b0;
digging <= 'b1;
end
F: begin
walk_left <= 'b0;
walk_right <= 'b0;
aaah <= 'b0;
digging <= 'b1;
end
G: begin
walk_left <= 'b0;
walk_right <= 'b0;
aaah <= 'b1;
digging <= 'b0;
end
H: begin
walk_left <= 'b0;
walk_right <= 'b0;
aaah <= 'b0;
digging <= 'b0;
end
endcase
end
end
// Output Second way ----> Combinational Logic
/*
assign walk_left = (cs == A);
assign walk_right = (cs == B);
assign aaah = (cs == C || cs == D);
assign digging = (cs == E || cs == F);
*/
endmodule
```
解題思路: 這一在解題過程中,我一開始沒有設定一個狀態(超過20cycle然後沒碰到地的情況),多設這個狀態可以在counter數到20的時候進入一個狀態,這個狀態可以保持ahhh一直叫的狀態但是觸地就splatter,若是沒有這狀態觸地會繼續行走,好比超過20就卡在另一個狀態只要等著碰到地就splatter其餘時間只管ahhh就好。
---------------------------------------------------------------
### One-hot FSM (@@)
```verilog=
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2);
assign next_state[0] = ~in & (state[0] | state[1] | state[2] | state[3] | state[4] | state[7] | state[8] | state[9]);
assign next_state[1] = in & (state[0] | state[8] | state[9]);
assign next_state[2] = in & state[1];
assign next_state[3] = in & state[2];
assign next_state[4] = in & state[3];
assign next_state[5] = in & state[4];
assign next_state[6] = in & state[5];
assign next_state[7] = in & (state[6] | state[7]);
assign next_state[8] = ~in & state[5];
assign next_state[9] = ~in & state[6];
// Output
assign out1 = state[8] | state[9];
assign out2 = state[7] | state[9];
endmodule
```
解題思路:這一題有要求(not the state filp-flop),所以要全部是組合邏輯電路,一開始我還是一樣像是用三段方式去寫,寫了很久搞死自己,其不用想那麼復雜,組合邏輯直接assign output在什麼情況會輸出為1就好了。
--------------------------------------------------
### PS/packet parser (解析器) (@@)
```verilog=
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3 ;
reg [2:0] ns,cs;
// State flip-flops (sequential)
always @(posedge clk) begin
if (reset) cs <= S0;
else cs <= ns;
end
// State transition logic (combinational)
always @(*) begin
case (cs)
S0: ns = in[3] ? S1 : S0;
S1: ns = S2;
S2: ns = S3;
S3: ns = in[3] ? S1 : S0;
default: ns = S0;
endcase
end
// Output logic
/*always @(posedge clk) begin
if(reset) done <= 'b0;
else begin
case (ns)
S0: done <= 'b0;
S1: done <= 'b0;
S2: done <= 'b0;
S3: done <= 'b1;
default: done <= 'b0;
endcase
end
end
*/
assign done = (cs == S3);
endmodule
```
解題思路:剛看到題目是完全不知如何下手,這個時候仔細觀察輸出與輸入關係,可以發現有一個循環例如:第一個in[3] = 1出現開始後的第三個cycle要是in[3] = 1,即輸出done = 1,這時候就可以畫出一個基本的狀態機的大圈圈,至於每一個state怎麼跳到下一個state再慢慢寫。
--------------------------------------------------------------------
### PS/packet paser and datapath (V)
```verilog=
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output reg [23:0] out_bytes,
output reg done); //
// FSM from fsm_ps2
parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3 ;
reg [2:0] ns,cs;
// State flip-flops (sequential)
always @(posedge clk) begin
if (reset) cs <= S0;
else cs <= ns;
end
// State transition logic (combinational)
always @(*) begin
case (cs)
S0: ns = in[3] ? S1 : S0;
S1: ns = S2;
S2: ns = S3;
S3: ns = in[3] ? S1 : S0;
default: ns = S0;
endcase
end
// Output logic
always @(posedge clk) begin
if(reset) begin
done <= 'b0;
out_bytes <= 'd0;
end
else begin
case (ns)
S0: done <= 'b0;
S1: begin
done <= 'b0;
out_bytes [23:16] <= in;
end
S2: begin
done <= 'b0;
out_bytes [15:8] <= in;
end
S3: begin
done <= 'b1;
out_bytes [7:0] <= in;
end
default: begin
done <= 'b0;
out_bytes <= 'dx;
end
endcase
end
end
//assign done = (cs == S3);
// New: Datapath to store incoming bytes.
endmodule
```
----------------------------------------------------
### Serial Receiver (@@)
```verilog=
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output done
);
// S0: start
parameter S0 = 4'd0, S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4;
parameter S5 = 4'd5, S6 = 4'd6, S7 = 4'd7, S8 = 4'd8, FF = 4'd9;
parameter STOP = 4'd10, S9 = 4'd11;
reg [3:0] cs, ns;
always @(posedge clk) begin
if (reset) begin
cs <= S0;
end else cs <= ns;
end
always @(*) begin
case(cs)
S0: ns = in ? S0 : S1; // start (0)
S1: ns = S2; // 1
S2: ns = S3; // 2
S3: ns = S4; // 3
S4: ns = S5; // 4
S5: ns = S6; // 5
S6: ns = S7; // 6
S7: ns = S8; // 7
S8: ns = S9; // 8
S9: ns = in ? STOP : FF; // end
STOP: ns = in ? S0 : S1; // HERE !!!!!!!!!!!!!!!!!!
FF: ns = in ? S0 : FF;
default: ns = S0;
endcase
end
assign done = (cs == STOP);
endmodule
```
解題思路: 這一題我在第31行卡了超久我一開始寫的是:
```verilog=31
STOP: ns = S0; // Line 31 is wrong
```

WRONG MESSAGE
如上圖,在110ns時候in = 1,下面done在下一個cycle就跳起來(狀態為STOP)
但是此時in = 0,狀態應該是要去S1,但我原本的寫法會造成直接跑去S0(錯誤邏輯)
所以在後面210ns時候再次遇到in = 1,我狀態會在S8,此時in為何不會影響輸出done。
-----------------------------------------------------------
### Serial receiver with parity checking (@@)
```verilog=
module top_module(
input clk,
input in,
input reset, // Synchronous reset
output reg [7:0] out_byte,
output done
);
// Use FSM from Fsm_serial
parameter S0 = 4'd0, S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4;
parameter S5 = 4'd5, S6 = 4'd6, S7 = 4'd7, S8 = 4'd8, FF = 4'd9;
parameter STOP = 4'd10, S9 = 4'd11;
parameter S10 = 4'd12; // past the parity bit
reg [3:0] cs, ns;
reg odd;
wire rst;
// parity checking
assign rst = (cs == STOP || cs == S0); // 注意地方:要加入cs == STOP
parity parity1(.clk(clk), .reset(rst), .in(in), .odd(odd));
always @(posedge clk) begin
if (reset) cs <= S0;
else cs <= ns;
end
always @(*) begin
case(cs)
S0: ns = in ? S0 : S1; // start
S1: ns = S2; // 1
S2: ns = S3; // 2
S3: ns = S4; // 3
S4: ns = S5; // 4
S5: ns = S6; // 5
S6: ns = S7; // 6
S7: ns = S8; // 7
S8: ns = S9; // 8
S9: ns = S10; // parity
S10: ns = in ? STOP : FF; // end
STOP: ns = in ? S0 : S1; // HERE
FF: ns = in ? S0 : FF;
default: ns = S0;
endcase
end
assign done = (cs == STOP && odd == 'b0); //odd = 0為奇數
// New: Datapath to latch input bits.
always @(posedge clk) begin
case (cs)
S1: out_byte[0] <= in;
S2: out_byte[1] <= in;
S3: out_byte[2] <= in;
S4: out_byte[3] <= in;
S5: out_byte[4] <= in;
S6: out_byte[5] <= in;
S7: out_byte[6] <= in;
S8: out_byte[7] <= in;
default out_byte <= out_byte;
endcase
end
endmodule
```
解題思路:
本題目加入Parity checking奇偶驗證,他會在8個bits資料後加上1bit作為驗證
* 需要滿足9位元中的1為奇數
* S9為Parity checking位元
檢討:在給odd parity module rst訊號時沒有加入cs == STOP,導致出錯。需要保持每一次需要進入S1開始計數奇數時module parity為乾淨的!!
-----------------------------------------------------------------
### Sequence recognition (V)
```verilog=
module top_module(
input clk,
input reset, // Synchronous reset
input in,
output disc,
output flag,
output err);
parameter S0 = 'd0, S1 = 'd1, S2 = 'd2, S3 = 'd3, S4 = 'd4, S5 = 'd5, S6 = 'd6;
parameter D = 'd7, F = 'd8, E = 'd9;
reg [3:0]cs, ns; // reg 制定位元是必須
always @(posedge clk) begin
if(reset) cs <= S0;
else cs <= ns;
end
always @(*)begin
case (cs)
S0: ns = in ? S1 : S0; // bit 1 None
S1: ns = in ? S2 : S0; // bit 2
S2: ns = in ? S3 : S0; // bit 3
S3: ns = in ? S4 : S0; // bit 4
S4: ns = in ? S5 : S0; // bit 5
S5: ns = in ? S6 : D; // disc bit 6
S6: ns = in ? E : F; // F1ag bit 7
D: ns = in ? S1 : S0; // ** 缺少為1時去S1
F: ns = in ? S1 : S0; // ** 缺少為1時去S1
E: ns = in ? E : S0;
endcase
end
assign disc = (cs == D);
assign flag = (cs == F);
assign err = (cs == E);
endmodule
```
-------------------------------------------------------------------
### Q8: Design a Mealy FSM

```verilog=
module top_module (
input clk,
input aresetn, // Asynchronous active-low reset
input x,
output z );
parameter S0 = 2'd0, S1 = 2'd1, S2 = 2'd2;
reg [1:0] cs, ns;
always @(posedge clk or negedge aresetn) begin
if(!aresetn) cs <= S0;
else cs <= ns;
end
always @(*) begin
case (cs)
S0: begin
if(x) ns = S2;
else ns = S0;
end
S1: begin
if(x) ns = S2;
else ns = S0;
end
S2: begin
if(x) ns = S2;
else ns = S1;
end
default: cs = cs;
endcase
end
assign z = ( x && cs == S1);
endmodule
```
解題思路: Mealy Machine的狀態圖是每個state圈圈中沒有輸出,而是在箭頭上會有(1/0)...之類的,表示輸出與輸入有關,Moore Machine則是輸出就在state的圈圈裡,搞懂這個畫圖遍歷過所有情況,再按照圖寫verilog就不會有問題了。
-------------------------------------------------------------------
### Q5a: Serial two's complementer(Moore FSM) (V)
```verilog=
module top_module (
input clk,
input areset,
input x,
output reg z
);
parameter S0 = 'd0, S1 = 'd1 , S2 = 'd2, S3 = 'd3;
reg [3:0] cs, ns;
always @(posedge clk or posedge areset) begin
if(areset) cs <= S0;
else cs <= ns;
end
always @(*) begin
case(cs)
S0: begin // First detect
if(x) ns = S1; // First 1
else ns = S3; // First 0
end
S1: begin
ns = S2;
end
S2: begin
ns = S2;
end
S3: begin
if (x) begin
ns = S1;
end else begin
ns = S3;
end
end
endcase
end
always @(posedge clk or posedge areset) begin
if(areset) z = 'd0;
else begin
case(ns)
S1: z <= 'd1;
S2: z <= ~x;
S3: z <= 'd0;
endcase
end
end
endmodule
```
-------------------------------------------------------
### Q5b Serial twos complementer (Mealy FSM) (V)
```verilog=
module top_module (
input clk,
input areset,
input x,
output reg z
);
parameter A = 1'b0, B = 1'b1;
reg cs, ns;
always @(posedge clk or posedge areset) begin
if(areset) cs <= A;
else cs <= ns;
end
always @(*) begin
case(cs)
A: ns <= x ? B : A;
B: ns <= B;
endcase
end
always @(*) begin
case (cs)
A: z = x ? 1 : 0;
B: z = x ? 1'b0 : 1'b1;
default: z = z;
endcase
end
endmodule
```
解題思路: Mealy FSM,**輸出與當先輸入有關**所以output block一定要用組合邏輯輸出哦!!
-------------------------------------------------
### Q3a: FSM (@@) - 可重點複習!
> Consider a finite state machine with inputs s and w. Assume that the FSM begins in a reset state called A, as depicted below. The FSM remains in state A as long as s = 0, and it moves to state B when s = 1. Once in state B the FSM examines the value of the input w in the next three clock cycles. If w = 1 in exactly two of these clock cycles, then the FSM has to set an output z to 1 in the following clock cycle. Otherwise z has to be 0. The FSM continues checking w for the next three clock cycles, and so on. The timing diagram below illustrates the required values of z for different values of w.
> Use as few states as possible. Note that the s input is used only in state A, so you need to consider just the w input.

```verilog=
// NOT BEST SOLUTION
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A = 4'd0, B = 4'd1, B1_0 = 4'd2, B1_1 = 4'd3, B2_0 = 4'd4, B2_1 = 4'd5, B2_2 = 4'd6, B3_2 = 4'd7, B3_x = 4'd8;
reg [3:0] cs, ns;
always @(*) begin
case (cs)
A: ns = s ? B : A;
B: ns = w ? B1_1 : B1_0;
B1_1: ns = w ? B2_2 : B2_1;
B1_0: ns = w ? B2_1 : B2_0;
B2_0: ns = w ? B3_x : B3_x;
B2_1: ns = w ? B3_2 : B3_x;
B2_2: ns = w ? B3_x : B3_2;
B3_2: ns = w ? B1_1 : B1_0;
B3_x: ns = w ? B1_1 : B1_0;
endcase
end
always @(posedge clk ) begin
if(reset) cs <= A;
else cs <= ns;
end
assign z = (cs == B3_2);
endmodule
```
解題思路:這一題一開始想太複雜,其實設一堆(9個states)就搞定了,但我也不知道有沒有其他方法,可能要參考一下[CSDN](https://blog.csdn.net/wangkai_2019/article/details/106471261#3.2.5.24%20Q3a%3A%20FSM%EF%BC%88Exams%2F2014%20q3fsm%EF%BC%89)-2025/03/14(看完CSDN答案...),重點就是在設B的state時候不要搞錯到底現在有幾個w=1。
這裡放一下CSDN答案好了,我個人覺得頗為複雜,但是的確符合題目要求的最少state。
CSDN and my design:CSDN的略勝一籌,在WNS大了一點點,但至少都比最原始一堆state的好。
#### CSDN 解答
```verilog=
// CSDN
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output z
);
parameter A = 1'b0, B = 1'b1;
reg current_state;
reg next_state;
always@(posedge clk)begin
if(reset)begin
current_state <= A;
end
else begin
current_state <= next_state;
end
end
always@(*)begin
case(current_state)
A:begin
next_state = s ? B : A;
end
B:begin
next_state = B;
end
endcase
end
reg w_reg1;
reg w_reg2;
always@(posedge clk)begin
if(reset)begin
w_reg1 <= 1'b0;
w_reg2 <= 1'b0;
end
else if(next_state == B)begin
w_reg1 <= w;
w_reg2 <= w_reg1;
end
else begin
w_reg1 <= 1'b0;
w_reg2 <= 1'b0;
end
end
always@(posedge clk)begin
if(reset)begin
z <= 1'b0;
end
else if(current_state == B && counter == 2'd0)begin
if(~w & w_reg1 & w_reg2 | w & ~w_reg1 & w_reg2 | w & w_reg1 & ~w_reg2)begin
z <= 1'b1;
end
else begin
z <= 1'b0;
end
end
else begin
z <= 1'b0;
end
end
reg [1:0] counter;
always@(posedge clk)begin
if(reset)begin
counter <= 2'd0;
end
else if(counter == 2'd2)begin
counter <= 2'd0;
end
else if(next_state == B)begin
counter <= counter + 1'b1;
end
end
endmodule
```
#### ANS 2:
一樣使用兩個state,但是與CSDN答案不一樣,使用counter記錄w=1的次數。
```verilog=
module top_module (
input clk,
input reset, // Synchronous reset
input s,
input w,
output reg z
);
// State definition: A -> initial, B -> counting state
parameter A = 1'd0, B = 1'd1;
reg cs, ns;
// State machine -> Transition from A -> B
always @(posedge clk) begin
if(reset) cs <= A;
else cs <= ns;
end
// Condition -> Combinational Logic
always @(*) begin
case(cs)
A: ns = s ? B : A;
B: ns = B;
default: ns = A;
endcase
end
// Counter: when in state B, use cycle_count to track 3 clock cycles,
//and use w_count to count occurrens of w = 1 within these cycles
//講人話就是:
//在狀態B下: cycle_count是上數3計數器
// w_count就是記 w = 1 的計數器
reg [1:0] cycle_count;
reg [1:0] w_count;
always @(posedge clk) begin
if (reset) begin
cycle_count <= 2'd0;
w_count <= 2'd0;
z <= 1'b0;
end
else if (cs == B) begin
// 當進入狀態 B 時開始計數
if(cycle_count == 2'd2)begin
//第三個cycle:先將當前 cycle 的w加入計數,再判斷 * 此舉非常重要 *
if(w_count + (w ? 1'b1 : 1'b0) == 2) z <= 1'b1;
else z <= 1'b0;
// 判斷後重置counter進入下一個 3-cycle 窗口
cycle_count <= 2'd0;
w_count <= 2'd0;
end
else begin
// in 前兩個cycle: 1. 累加 cycle 和 w 的次數; 2. z仍為 0
cycle_count <= cycle_count +1'b1;
w_count <= w_count + (w ? 1'b1 : 1'b0);
z <= 1'b0;
end
end
else begin
// 當不在狀態 B ,保持所有counter = 0, z = 0
cycle_count <= 2'd0;
w_count <= 2'd0;
z <= 1'b0;
end
end
endmodule
```
-----------------------------------------------------------------
### Q3b: FSM (V)

解題思路:這題很簡單,只是在最後的 output logic 的時候使用 if(cs) 還是 if(cs) 中有了疑惑,以往遇到這種問題都會用try的方式反正不行就換另一種,但是要了解其原理才是真的。
以下是簡短整理:
- **使用 current_state 輸出:**
- 常用於 Moore 型 FSM。
- 輸出完全依賴目前狀態,因此狀態穩定時輸出穩定。
- 更新在時鐘邊緣發生,所以輸出延遲一個 clock 週期。
- **使用 next_state 輸出:**
- 常用於 Mealy 型 FSM 或是需要提前預測狀態的情況。
- 輸出可能與狀態轉換前的邏輯相關,可減少延遲,但可能較複雜且容易產生毛刺。
總結來說,若追求簡單穩定且易於分析的設計,建議以 current_state 作為輸出依據;若需要更快反應(但要注意可能的毛刺),則可以考慮用 next_state。
```verilog=
module top_module (
input clk,
input reset, // Synchronous reset
input x,
output reg z
);
// Define satte total five states
parameter S000 = 3'd0, S001 = 3'd1, S010 = 3'd2, S011 = 3'd3, S100 = 3'd4;
reg [2:0] current_state, next_state;
// State machine
always @(posedge clk) begin
if(reset) current_state <= S000;
else current_state <= next_state;
end
always@(*)begin
case(current_state)
S000: next_state = x ? S001 : S000;
S001: next_state = x ? S100 : S001;
S010: next_state = x ? S001 : S010;
S011: next_state = x ? S010 : S001;
S100: next_state = x ? S100 : S011;
default: next_state = S000;
endcase
end
// Output Logic
always@(posedge clk)begin
if(reset) z <= 1'b0;
else begin
if(next_state == S011 || next_state == S100) // 一開始我寫 current state
// 在 Sequence Block中,滿足條件式的當下需要等 clock edge 來的時候才會更新
// 請注意不要再犯這種白癡問題
z <= 1'b1;
else
z <= 1'b0;
end
end
endmodule
```
-----------------------------------------------------------------
### Q3c: FSM Logic (V)

解題思路:這一天基本上用不到clk,(Vscode這裡用verilog套件,這種output沒有寫reg會報錯是正常)。這題完全是用組合邏輯實現,我自己寫的是方法一,CSDN是方法二。這題看看就好。
方法一:
```verilog=
module top_module (
input clk,
input [2:0] y,
input x,
output Y0,
output z
);
parameter S000 = 3'd0, S001 = 3'd1, S010 = 3'd2, S011 = 3'd3, S100 = 3'd4;
// 這個寫法完全是 Combination Logic 電路,沒用到clk
always @(*) begin
case(y)
S000: begin
Y0 = x ? 1'b1 : 1'b0;
z = 1'b0;
end
S001: begin
Y0 = x ? 1'b0 : 1'b1;
z = 1'b0;
end
S010: begin
Y0 = x ? 1'b1 : 1'b0;
z = 1'b0;
end
S011: begin
Y0 = x ? 1'b0 : 1'b1;
z = 1'b1;
end
S100: begin
Y0 = x ? 1'b0 : 1'b1;
z = 1'b1;
end
endcase
end
endmodule
```
方法二:
```verilog=
module top_module (
input clk,
input [2:0] y,
input x,
output Y0,
output z
);
assign Y0 = (x & y == 3'b000 || ~x & y == 3'b001 || x & y == 3'b010 || ~x & y == 3'b011 || ~x & y == 3'b100);
assign z =(y == 3'b011 || y == 3'b100);
endmodule
```
-----------------------------------------------------------------
### Q6b: FSM next-state logic (V)

方法一:
```verilog=
module top_module (
input [3:1] y,
input w,
output reg Y2);
parameter A = 3'd0, B = 3'd1, C = 3'd2, D = 3'd3, E = 3'd4, F = 3'd5;
always @(*) begin
case(y)
A:begin
Y2 = 1'b0;
end
B:begin
Y2 = 1'b1;
end
C:begin
Y2 = w ? 1'b1 : 1'b0;
end
D:begin
Y2 = 1'b0;
end
E:begin
Y2 = w ? 1'b1 : 1'b0;
end
F:begin
Y2 = 1'b1;
end
default: Y2 = 1'b0;
endcase
end
endmodule
```
方法二:
```verilog=
module top_module (
input [3:1] y,
input w,
output Y2);
assign Y2 = (y == 3'b001 || y == 3'b101 || w & y == 3'b010 || w & y == 3'b100);
endmodule
```
-----------------------------------------------------------------
### Q6c: FSM one-hot one-hot logic(Exams/m2014 q6c) (V)
#### One-hot 獨熱碼:
**One-hot(獨熱碼)** 是一種 **數字編碼方式**,在 **N 位元** 的編碼中,只有 **一個位元為 1,其餘皆為 0**。
#### **特性**:
- **唯一性**:每個狀態對應 **一個唯一的位置為 `1`**,其餘皆為 `0`。
- **容易實現**:在 **有限狀態機(FSM)** 中,因為每個狀態只需檢查一個位元,轉換邏輯較簡單。
- **較多位元**:相比於二進位編碼,One-hot 需要 **更多位元**(`N` 個狀態需要 `N` 個位元)。
#### **範例**
假設有 4 個狀態:
| 狀態 | One-hot 編碼 |
|------|-------------|
| S0 | `0001` |
| S1 | `0010` |
| S2 | `0100` |
| S3 | `1000` |
#### **應用**
- **FSM(有限狀態機)設計**
- **編碼分類問題(機器學習、深度學習)**
- **記憶體地址選擇(解碼器)**
相比於傳統的二進位編碼,**One-hot 編碼適用於 FPGA 和 ASIC 設計中的狀態機,因為它簡化了狀態轉換邏輯,提升時序效能**。
```verilog=
module top_module (
input [6:1] y,
input w,
output reg Y2,
output reg Y4);
parameter A = 1, B = 2, C = 3, D = 4, E = 5, F = 6;
assign Y2 = ~w & y[A];
assign Y4 = w & (y[B] | y[C] | y[E] | y[F]);
endmodule
```
解題思路:這一題我一開始怎麼寫都過不了,結果仔細解讀題目描述,他意思是說就算輸入不是獨熱碼也照樣執行,不需要排除多bit為1的情況。(原本我寫的是用case讓y只match獨熱碼...)。
-----------------------------------------------------------------
### Q6: FSM (Exams/m2014 q6) (V)
> Consider the state machine shown below, which has one input w and one output z.

Implement the state machine. (This part wasn't on the midterm, but coding up FSMs is good practice).
```verilog=
module top_module (
input clk,
input reset, // synchronous reset
input w,
output reg z);
parameter A = 3'd0, B = 3'd1, C = 3'd2, D = 3'd3, E = 3'd4, F = 3'd5;
reg [2:0] current_state, next_state;
always @(posedge clk) begin
if(reset) current_state <= A;
else current_state <= next_state;
end
always @(*) begin
case(current_state)
A: next_state = w ? A : B;
B: next_state = w ? D : C;
C: next_state = w ? D : E;
D: next_state = w ? A : F;
E: next_state = w ? D : E;
F: next_state = w ? D : C;
default: next_state = A;
endcase
end
always @(posedge clk) begin
if(reset) z <= 1'b0;
else begin
case(next_state)
A: z <= 1'b0;
B: z <= 1'b0;
C: z <= 1'b0;
D: z <= 1'b0;
E: z <= 1'b1;
F: z <= 1'b1;
default: z <= 1'b0;
endcase
end
end
endmodule
```
解題思路:這題是一點難度都沒有。
-----------------------------------------------------------------
### Q2a: FSM (Exams/2012 q2fsm) (V)
> Consider the state diagram shown below.
> 
> Write complete Verilog code that represents this FSM. Use separate always blocks for the state table and the state flip-flops, as done in lectures. Describe the FSM output, which is called z, using either continuous assignment statement(s) or an always block (at your discretion). Assign any state codes that you wish to use.
```verilog=
module top_module (
input clk,
input reset, // Synchronous active-high reset
input w,
output z
);
parameter A = 3'd0, B = 3'd1, C = 3'd2, D = 3'd3, E = 3'd4, F = 3'd5;
reg [2:0] current_state, next_state;
always @(posedge clk) begin
if(reset) current_state <= A;
else current_state <= next_state;
end
always @(*) begin
case(current_state)
A: next_state = w ? B : A;
B: next_state = w ? C : D;
C: next_state = w ? E : D;
D: next_state = w ? F : A;
E: next_state = w ? E : D;
F: next_state = w ? C : D;
default: next_state = A;
endcase
end
always @(posedge clk) begin
if(reset) z <= 1'b0;
else begin
case(next_state)
A: z <= 1'b0;
B: z <= 1'b0;
C: z <= 1'b0;
D: z <= 1'b0;
E: z <= 1'b1;
F: z <= 1'b1;
default: z <= 1'b0;
endcase
end
end
endmodule
```
解題思路:跟上一題幾乎一模一樣,無難度。
-----------------------------------------------------------------
### Q2b: One-hot FSM questions(Exams/2012 q2b) (V)
>The state diagram for this question is shown again below.
>
>Assume that a one-hot code is used with the state assignment y[5:0] = 000001(A), 000010(B), 000100(C), 001000(D), 010000(E), 100000(F)
>
>Write a logic expression for the signal Y1, which is the input of state flip-flop y[1].
>
>Write a logic expression for the signal Y3, which is the input of state flip-flop y[3].
>
>(Derive the logic equations by inspection assuming a one-hot encoding. The testbench will test with non-one hot inputs to make sure you're not trying to do something more complicated).
```verilog=
module top_module (
input [5:0] y,
input w,
output Y1,
output Y3
);
assign Y1 = w & y[0];
assign Y3 = ~w &(y[1] | y[2] | y[4] | y [5]);
endmodule
```
解題思路: 組合邏輯。
-----------------------------------------------------------------
### Q2: FSM (Exams/2013 q2afsm) (V)
>Consider the FSM described by the state diagram shown below:
>
>This FSM acts as an arbiter circuit, which controls access to some type of resource by three requesting devices. Each device makes its request for the resource by setting a signal r[i] = 1, where r[i] is either r[1], r[2], or r[3]. Each r[i] is an input signal to the FSM, and represents one of the three devices. The FSM stays in state A as long as there are no requests. When one or more request occurs, then the FSM decides which device receives a grant to use the resource and changes to a state that sets that device’s g[i] signal to 1. Each g[i] is an output from the FSM. There is a priority system, in that device 1 has a higher priority than device 2, and device 3 has the lowest priority. Hence, for example, device 3 will only receive a grant if it is the only device making a request when the FSM is in state A. Once a device, i, is given a grant by the FSM, that device continues to receive the grant as long as its request, r[i] = 1.
>
>Write complete Verilog code that represents this FSM. Use separate always blocks for the state table and the state flip-flops, as done in lectures. Describe the FSM outputs, g[i], using either continuous assignment statement(s) or an always block (at your discretion). Assign any state codes that you wish to use.
```verilog=
module top_module (
input clk,
input resetn, // active-low synchronous reset
input [3:1] r, // request
output reg [3:1] g // grant
);
parameter A = 2'd0, B = 2'd1, C = 2'd2, D = 2'd3;
reg [1:0] current_state, next_state;
// 最一開始的寫法
//always @(*) begin
// next_state <= r[1] ? B : (r[2] ? C : (r[3] ? D : A));
//end
always @(*) begin
case (current_state)
A: next_state <= r[1] ? B : (r[2] ? C : (r[3] ? D : A));
B: next_state <= r[1] ? B : A;
C: next_state <= r[2] ? C : A;
D: next_state <= r[3] ? D : A;
default: next_state <= 3'd0;
endcase
end
always @(posedge clk) begin
if(!resetn) current_state <= A;
else current_state <= next_state;
end
always @(posedge clk) begin
if(!resetn) g <= 3'd0;
else begin
case(next_state)
A: g <= 3'd0;
B: g <= 3'd1;
C: g <= 3'd2;
D: g <= 3'd4;
default: g <= 3'd0;
endcase
end
end
endmodule
```
解題思路:這一題蠻有趣的,但總共寫了兩次也就過了。我最一開始的寫法如注釋中,我沒註意到每一個state會先判斷他那個signal是否還在,若不在的話就會回到起點state A,我就是漏掉這一步。
-----------------------------------------------------------------
### Q2b: Another FSM (Exams/2013 q2bfsm)
>Consider a finite state machine that is used to control some type of motor. The FSM has inputs x and y, which come from the motor, and produces outputs f and g, which control the motor. There is also a clock input called clk and a reset input called resetn.
>
>The FSM has to work as follows. As long as the reset input is asserted, the FSM stays in a beginning state, called state A. When the reset signal is de-asserted, then after the next clock edge the FSM has to set the output f to 1 for one clock cycle. Then, the FSM has to monitor the x input. When x has produced the values 1, 0, 1 in three successive clock cycles, then g should be set to 1 on the following clock cycle. While maintaining g = 1 the FSM has to monitor the y input. If y has the value 1 within at most two clock cycles, then the FSM should maintain g = 1 permanently (that is, until reset). But if y does not become 1 within two clock cycles, then the FSM should set g = 0 permanently (until reset).
>
>(The original exam question asked for a state diagram only. But here, implement the FSM.)
題目翻譯
考慮一個有限狀態機(FSM),該 FSM 用於控制某種類型的馬達。FSM 有以下輸入和輸出:
輸入訊號:
- `x` 和 `y`:來自馬達的輸入訊號
- `clk`:時脈訊號
- `resetn`:低電位有效的重置訊號
輸出訊號:
- `f` 和 `g`:控制馬達的輸出訊號
---
FSM 的運作規則
1. 重置狀態
當 `resetn` 被啟動(低電位)時,FSM 保持在初始狀態 `A`。
2. 啟動輸出 `f`
當 `resetn` 解除(變為高電位)後,FSM 在 **下一個時脈上升沿** 將 `f` 設為 `1`,但 **僅維持一個時脈週期**。
3. 監測輸入 `x`
當 `x` 在連續三個時脈週期內出現 `1 → 0 → 1`,則 FSM 在 **下一個時脈週期** 將 `g` 設為 `1`。
4. 監測輸入 `y`
當 `g` 被設為 `1` 後,FSM 開始監測 `y`。
- 若在接下來的 **兩個時脈週期內** `y` 變為 `1`,則 `g` **保持為 1**,直到重置發生。
- 若 `y` 在這兩個時脈內都沒有變為 `1`,則 `g` 設為 `0`,並保持為 `0`,直到重置發生。
(原始考題僅要求繪製狀態圖,但在這裡,請實作 FSM 的 **Verilog 代碼**。)
```verilog=
module top_module (
input clk,
input resetn, // active-low synchronous reset
input x,
input y,
output f,
output g
);
parameter [3:0] IDLE = 4'd0, F_PLUSE = 4'd1, S1 = 4'd2, S2 = 4'd3, S3 = 4'd4, Y_PLUSE = 4'd5, Y_WAIT = 4'd6, FOREVER_1 = 4'd7, FOREVER_0 = 4'd8;
reg [3:0] current_state, next_state;
always @(posedge clk) begin
if(!resetn) current_state <= IDLE;
else current_state <= next_state;
end
always @(*) begin
case (current_state)
IDLE: next_state = F_PLUSE;
F_PLUSE: next_state = S1;
S1: next_state = x ? S2 : S1;
S2: next_state = x ? S2 : S3;
S3: next_state = x ? Y_PLUSE : S1;
Y_PLUSE: next_state = y ? FOREVER_1 : Y_WAIT;
Y_WAIT: next_state = y ? FOREVER_1 : FOREVER_0;
FOREVER_1: next_state = FOREVER_1;
FOREVER_0: next_state = FOREVER_0;
default: next_state = IDLE;
endcase
end
assign f = (current_state == F_PLUSE);
assign g = (current_state == Y_PLUSE || current_state ==Y_WAIT || current_state == FOREVER_1);
endmodule
```
chatgpt注釋版本
```verilog=
module top_module (
input clk, // 時脈信號
input resetn, // 低有效同步重置
input x, // 馬達輸入 x 信號
input y, // 馬達輸入 y 信號
output f, // 控制輸出 f
output g // 控制輸出 g
);
// 狀態編碼 (4-bit)
parameter [3:0]
IDLE = 4'd0, // 初始狀態 A,reset 後進入
F_PLUSE = 4'd1, // f 脈衝輸出狀態 (僅一拍)
S1 = 4'd2, // 偵測 x == 1 的第一拍
S2 = 4'd3, // 偵測 x == 0
S3 = 4'd4, // 偵測 x == 1 完成 1-0-1 序列
Y_PLUSE = 4'd5, // g 脈衝輸出狀態 (一拍)
Y_WAIT = 4'd6, // 等待 y 在兩拍內變為 1
FOREVER_1 = 4'd7, // g 永久為 1 (直到 reset)
FOREVER_0 = 4'd8; // g 永久為 0 (直到 reset)
// 狀態暫存器
reg [3:0] current_state, next_state;
// 同步狀態更新:posedge clk 觸發,resetn 低電位時回到 IDLE
always @(posedge clk) begin
if (!resetn)
current_state <= IDLE;
else
current_state <= next_state;
end
// 組合邏輯:根據 current_state 和輸入決定 next_state
always @(*) begin
case (current_state)
IDLE: next_state = F_PLUSE; // reset 解除後,下一拍產生 f 脈衝
F_PLUSE: next_state = S1; // 脈衝完成後開始監測 x
S1: next_state = x ? S2 : S1; // x=1 進 S2;否則停留
S2: next_state = x ? S2 : S3; // x=1 保持;x=0 進 S3
S3: next_state = x ? Y_PLUSE : S1; // 1-0-1 完成進 Y_PLUSE;否則回 S1
Y_PLUSE: next_state = y ? FOREVER_1 : Y_WAIT; // g 脈衝後根據 y 決定
Y_WAIT: next_state = y ? FOREVER_1 : FOREVER_0; // 等待第二拍 y
FOREVER_1: next_state = FOREVER_1; // 永久保持 g=1
FOREVER_0: next_state = FOREVER_0; // 永久保持 g=0
default: next_state = IDLE; // 預設回 IDLE
endcase
end
// 輸出 f: 當前狀態為 F_PLUSE 時輸出 1
assign f = (current_state == F_PLUSE);
// 輸出 g: 當前狀態為 Y_PLUSE、Y_WAIT 或 FOREVER_1 時輸出 1
assign g = (current_state == Y_PLUSE) ||
(current_state == Y_WAIT) ||
(current_state == FOREVER_1);
endmodule
```
解題思路:這題不能使用counter數1個數,因為題目要求固定的格式(1-0-1)所以我是使用多個state完成,但其實應該也可以用之前CSDN使用的mask方式完成。
這裡補充一下 Y_PULSE其實應該是G_PLUSE但我懶得改哈哈。
-------------------------------------------------------------
# Building Larger Circuit
### Counter with period 1000 (Exams/review2015 count1k)
>Build a counter that counts from 0 to 999, inclusive, with a period of 1000 cycles. The reset input is synchronous, and should reset the counter to 0.
>
```verilog=
module top_module (
input clk,
input reset,
output [9:0] q);
// reg [9:0] cnt1000;
always @(posedge clk) begin
if(reset) q <= 10'd0;
else if(q == 10'd999)begin
q <= 10'd0;
end
else begin
q <= q + 10'd1;
end
end
endmodule
```
---------------------------------------------------------------------
### 4-bit shift register and down counter (Exams/review2015shiftcount)
>This is the first component in a series of five exercises that builds a complex counter out of several smaller circuits. See the final exercise for the overall design.
>
>Build a four-bit shift register that also acts as a down counter. Data is shifted in most-significant-bit first when shift_ena is 1. The number currently in the shift register is decremented when count_ena is 1. Since the full system doesn't ever use shift_ena and count_ena together, it does not matter what your circuit does if both control inputs are 1 (This mainly means that it doesn't matter which case gets higher priority).
>
```verilog=
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output reg [3:0] q);
// reg [3:0] q_reg;
always @(posedge clk) begin
if (shift_ena) begin
q <= {q[2:0], data};
end else if (count_ena) begin
q <= q - 4'd1;
end
end
endmodule
```
----------------------------------------------------------------------
### FSM: Sequence 1101 recognizer (Exams/review2015fsmseq)
>This is the second component in a series of five exercises that builds a complex counter out of several smaller circuits. See the final exercise for the overall design.
>
>Build a finite-state machine that searches for the sequence 1101 in an input bit stream. When the sequence is found, it should set start_shifting to 1, forever, until reset. Getting stuck in the final state is intended to model going to other states in a bigger FSM that is not yet implemented. We will be extending this FSM in the next few exercises.
>
```verilog=
module top_module (
input clk, // 時鐘輸入
input reset, // 同步重置 (高有效)
input data, // 串列資料輸入
output reg start_shifting // 偵測到 4-bit 模式 1101 後置高,並保持高電位
);
// 用來儲存最近三個時鐘週期的 data 值
reg first, second, third;
// 簡單兩狀態 FSM 的狀態暫存器
reg [1:0] current_state, next_state;
parameter IDLE = 2'd0, // 空閒,等待輸入模式
FOREVER_1 = 2'd1; // 偵測到模式後永久保持 start_shifting = 1
//===========================================================
// 狀態暫存器:時鐘上升沿時更新 current_state
//===========================================================
always @(posedge clk) begin
if (reset) begin
current_state <= IDLE; // 重置時回到 IDLE
end else begin
current_state <= next_state; // 否則進入 next_state
end
end
//===========================================================
// 移位暫存器:將 data 的最新三個值保存在 first/second/third
// first <= 最新的 data
// second <= 上一個 first
// third <= 上一個 second
//===========================================================
always @(posedge clk) begin
if (reset) begin
first <= 1'b0;
second <= 1'b0;
third <= 1'b0;
end else begin
first <= data; // 捕捉當前輸入
second <= first; // 向後移位
third <= second;
end
end
//===========================================================
// 下一狀態組合邏輯:檢查 4-bit 窗口 {third, second, first, data}
// 是否等於 1101
//===========================================================
always @(*) begin
case (current_state)
IDLE: begin
if ({third, second, first, data} == 4'b1101) begin
next_state = FOREVER_1; // 找到 1101 → 進入 FOREVER_1
end else begin
next_state = IDLE; // 否則保持 IDLE
end
end
FOREVER_1: begin
next_state = FOREVER_1; // 永遠保持在 FOREVER_1
end
default: begin
next_state = IDLE; // 安全預設
end
endcase
end
//===========================================================
// 輸出邏輯:start_shifting 在 FOREVER_1 狀態下為 1
//===========================================================
always @(posedge clk) begin
if (reset || next_state == IDLE) begin
start_shifting <= 1'b0; // 重置或回到 IDLE 時拉低
end else begin
start_shifting <= 1'b1; // 在 FOREVER_1 時拉高
end
end
endmodule
```
解題思路:遇到檢查bitstream不要傻傻地設一堆stage,然後一個bit一個stage,用register存下最近的bit+data {先前bit, data} == (期望pattern)的方式可以節省很多面積。
--------------------------------------------------------------------
### FSM: The Enable shift register
>This is the third component in a series of five exercises that builds a complex counter out of several smaller circuits. See the final exercise for the overall design.
>
>As part of the FSM for controlling the shift register, we want the ability to enable the shift register for exactly 4 clock cycles whenever the proper bit pattern is detected. We handle sequence detection in Exams/review2015_fsmseq, so this portion of the FSM only handles enabling the shift register for 4 cycles.
>
>Whenever the FSM is reset, assert shift_ena for 4 cycles, then 0 forever (until reset).
>
```verilog=
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg [2:0] current_state, next_state;
parameter IDLE = 3'd0, FOUR_CYCLE_ONE = 3'd1, FOREVER_ZERO = 3'd2;
reg DONE;
reg [2:0] cnt;
always @(posedge clk) begin
if (reset) begin
current_state <= IDLE;
end else begin
current_state <= next_state;
end
end
always @(*) begin
case(current_state)
IDLE: next_state = FOUR_CYCLE_ONE;
FOUR_CYCLE_ONE: next_state = DONE ? FOREVER_ZERO : FOUR_CYCLE_ONE;
FOREVER_ZERO: next_state = FOREVER_ZERO;
default: next_state = IDLE;
endcase
end
always @(posedge clk) begin
if(reset)begin
cnt <= 2'd0;
DONE <= 1'b0;
end
else if (next_state == FOUR_CYCLE_ONE) begin // 注意這裡
if(cnt == 3'd3) begin
cnt <= 3'd0;
DONE <= 1'b1;
end
else cnt++;
end
end
assign shift_ena = (next_state == FOUR_CYCLE_ONE);
endmodule
```
解題思路:在判斷counter何時開始計數的時候需要以next_state做判斷,這樣才不會多算一個cycle,輸出也需要看next_cycle。
不小心寫出最佳解 呵呵
------------------------------------------------------------------
### FSM: The complete FSM
>This is the fourth component in a series of five exercises that builds a complex counter out of several smaller circuits. See the final exercise for the overall design.
>You may wish to do FSM: Enable shift register and FSM: Sequence recognizer first.
>We want to create a timer that:
>1.is started when a particular pattern (1101) is detected,
>2.shifts in 4 more bits to determine the duration to delay,
3.waits for the counters to finish counting, and
4.notifies the user and waits for the user to acknowledge the timer.
>In this problem, implement just the finite-state machine that controls the timer. The data path (counters and some comparators) are not included here.
>
>The serial data is available on the data input pin. When the pattern 1101 is received, the state machine must then assert output shift_ena for exactly 4 clock cycles.
>
>After that, the state machine asserts its counting output to indicate it is waiting for the counters, and waits until input done_counting is high.
>
>At that point, the state machine must assert done to notify the user the timer has timed out, and waits until input ack is 1 before being reset to look for the next occurrence of the start sequence (1101).
>
>The state machine should reset into a state where it begins searching for the input sequence 1101.
>
>Here is an example of the expected inputs and outputs. The 'x' states may be slightly confusing to read. They indicate that the FSM should not care about that particular input signal in that cycle. For example, once a 1101 pattern is detected, the FSM no longer looks at the data input until it resumes searching after everything else is done.
>
```verilog=
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output shift_ena,
output counting,
input done_counting,
output done,
input ack );
// MAC HOME = FN / CMD + <-
// MAC END = FN / CMD + ->
// Start when a Particular pattern 1101 is detected
// shifts in 4 more bits
// waits for the counter finsh the counting
// Notifies the user and waits the user to acknowledge the timer
reg first, second, thrid;
reg [3:0] current_state, next_state;
reg [1:0] cnt; // counter 4 register
wire DONE_4; // Counter 4 done
parameter [3:0] IDLE = 4'd0, SHIFT = 4'd1, COUNTING = 4'd2, DONE = 4'd3, ACK = 4'd4;
// STATE REGISTER
always @(posedge clk) begin
if (reset) begin
current_state <= IDLE;
end else begin
current_state <= next_state;
end
end
// Pattern 1101 Detection paser
always @(posedge clk) begin
if(reset)begin
first <= 1'b0;
second <= 1'b0;
thrid <= 1'b0;
end
else if (current_state == IDLE)begin
first <= data; // 將 data 依序 按照 「third ; second ; first ; data」
second <= first;
thrid <= second;
end
end
assign DONE_4 = (cnt == 2'd3);
// COUNTER 4
always @(posedge clk)begin
if(reset)begin
cnt <= 2'd0;
end
else if (current_state == SHIFT)begin
if(cnt == 2'd3)begin
cnt <= 2'd0;
end
else cnt++;
end else begin
cnt <= 2'd0;
end
end
always @(*) begin
case(current_state)
IDLE: begin
if({thrid, second, first, data} == 4'b1101)begin
next_state = SHIFT; // 偵查到 pattern 1101 時候,跳到 SHIFT State
end
else begin
next_state = IDLE;
end
end
SHIFT: next_state = DONE_4 ? COUNTING : SHIFT;
COUNTING: next_state = done_counting ? DONE : COUNTING;
DONE: next_state = ack ? ACK : DONE;
ACK: next_state = IDLE;
default: next_state <= IDLE;
endcase
end
assign shift_ena = (current_state == SHIFT);
assign counting = (current_state == COUNTING);
assign done = (current_state == DONE);
endmodule
```
解題思路:這次學到新的一招,可以透過 assign DONE_4 = (cnt == 2'd3);
在當counter滿足條件時候指定wire為1,比我之前的指定reg來的好。
------------------------------------------------------------------
### FSM: The complete Timer