shinhao
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    F# verilog練習紀錄 ## Moore Machine (摩爾狀態機) 摩爾型有限狀態機(英語:Moore machine)是指輸出只由當前的狀態所確定的有限狀態自動機。具體來說會結合一個輸入,然後根據現在狀態判斷下一個狀態,摩爾型有限狀態機的狀態圖對每個狀態包含一個輸出訊號 ### Lemmings1 ```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, ... parameter LEFT = 0, RIGHT = 1; reg state, next_state; always @(*) begin next_state = state; case(state) LEFT : next_state = bump_left? RIGHT : LEFT; RIGHT : next_state = bump_right? LEFT : RIGHT; endcase // State transition logic end always @(posedge clk, posedge areset) begin // State flip-flops with asynchronous reset if (areset) state <= LEFT; else state <= next_state ; end // Output logic assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); endmodule ``` ### Lemmings2 跟Lemmings1差異在於,除了能夠向左和向右行走之外,當下面的地面消失時,Lemmings 會掉落(會喊 "aaah!")。 除了向左和向右行走以及在撞到障礙物時改變方向之外,當 ground=0 時,Lemming 會掉落。當地面重新出現(ground=1)時,Lemming 會恢復到掉落前相同的行走方向。掉落時受到撞擊不會影響其行走方向,而且在地面消失(ground = 0)或在地面重新出現時仍處於掉落狀態時(aash = 1)受到撞擊,也不會影響行走方向。 ```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 LEFT = 0, RIGHT = 1, GROUND_LEFT = 2 , GROUND_RIGHT = 3; reg [1:0]state; reg [1:0]next; always@(*)begin case(state) LEFT : next = ground? (bump_left?RIGHT:LEFT) : GROUND_LEFT; RIGHT : next = ground? (bump_right? LEFT : RIGHT) : GROUND_RIGHT; GROUND_LEFT : next = ground ? LEFT : GROUND_LEFT; GROUND_RIGHT: next =ground ? RIGHT : GROUND_RIGHT; default: next = LEFT; endcase end always@(posedge clk, posedge areset)begin if (areset) state <= LEFT; else state <= next; end assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); assign aaah = (state == GROUND_LEFT || state == GROUND_RIGHT); endmodule ``` ### Lemmings3 跟 Lemmings2 類似,只是要多新增兩個的digging狀態,如果有在地面(ground == 1),就要先判斷是否挖洞,否則就可以往左或右前進 ```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 = 0, RIGHT = 1, GROUND_LEFT = 2 , GROUND_RIGHT = 3, DIGGING_LEFT = 4, DIGGING_RIGHT = 5; reg [2:0]state; reg [2:0]next; always@(*)begin case(state) LEFT : next = ground? (dig ? DIGGING_LEFT: (bump_left?RIGHT:LEFT)) : GROUND_LEFT; RIGHT : next = ground? (dig ? DIGGING_RIGHT : (bump_right? LEFT : RIGHT)) : GROUND_RIGHT; GROUND_LEFT : next = ground ? LEFT : GROUND_LEFT; GROUND_RIGHT: next =ground ? RIGHT : GROUND_RIGHT; DIGGING_LEFT: next= ground ? DIGGING_LEFT : GROUND_LEFT; DIGGING_RIGHT : next = ground ? DIGGING_RIGHT :GROUND_RIGHT; default: next = LEFT; endcase end always@(posedge clk, posedge areset)begin if (areset) state <= LEFT; else state <= next; end assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); assign digging =(state == DIGGING_LEFT || state == DIGGING_RIGHT); assign aaah = (state == GROUND_LEFT || state == GROUND_RIGHT); endmodule ``` ### Lemmings4 ```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 = 0, RIGHT = 1, GROUND_LEFT = 2 , GROUND_RIGHT = 3, DIGGING_LEFT = 4, DIGGING_RIGHT = 5; parameter SPLATTER = 6, AAAH_END = 7; reg [2:0]state; reg [2:0]next; reg [4:0]counter; always@(*)begin case(state) LEFT : next = ground? (dig ? DIGGING_LEFT: (bump_left?RIGHT:LEFT)) : GROUND_LEFT; RIGHT : next = ground? (dig ? DIGGING_RIGHT : (bump_right? LEFT : RIGHT)) : GROUND_RIGHT; GROUND_LEFT : next = ground ? LEFT : (counter == 20 ? SPLATTER : GROUND_LEFT); GROUND_RIGHT: next =ground ? RIGHT : (counter == 20 ? SPLATTER : GROUND_RIGHT); DIGGING_LEFT: next= ground ? DIGGING_LEFT : GROUND_LEFT; DIGGING_RIGHT : next = ground ? DIGGING_RIGHT :GROUND_RIGHT; SPLATTER: next = ground? AAAH_END : SPLATTER; AAAH_END : next = AAAH_END; default: next = LEFT; endcase end always@(posedge clk, posedge areset)begin if (areset)begin state <= LEFT; counter <= 0; end else if(next == GROUND_LEFT || next == GROUND_RIGHT)begin state <= next; counter <= counter + 1; end else begin state <= next; counter <= 0; end end assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); assign digging =(state == DIGGING_LEFT || state == DIGGING_RIGHT); assign aaah = (state == GROUND_LEFT || state == GROUND_RIGHT || state == SPLATTER); endmodule ``` 正確ex1: https://github.com/M-HHH/HDLBits_Practice_verilog/blob/master/130.%20Lemmings%204.v ```verilog= //csdn網友提供解答 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=0, RIGHT=1, FALL_L=2, FALL_R=3, DIG_L=4, DIG_R=5, SPLAT=6; reg [2:0] state, next; reg [6:0] counter; //State Transition Logic always@(*) begin case (state) LEFT : next = ground ? (dig ? DIG_L:(bump_left ? RIGHT:LEFT)):FALL_L; RIGHT : next = ground ? (dig ? DIG_R:(bump_right ? LEFT:RIGHT)):FALL_R; FALL_L: next = ground ? (counter > 5'd20 ? SPLAT:LEFT) :FALL_L; FALL_R: next = ground ? (counter > 5'd20 ? SPLAT:RIGHT):FALL_R; DIG_L : next = ground ? DIG_L:FALL_L; DIG_R : next = ground ? DIG_R:FALL_R; SPLAT : next = SPLAT; default next = 'x; endcase end //State Flip-flops always@(posedge clk, posedge areset) begin if (areset) state <= LEFT; //The only way to jump out of SPLAT else state <= next; end //Counter for falling period always@(posedge clk, posedge areset) begin if (areset) begin counter <= 5'd0; end else begin if (~ground) counter <= counter+1'b1; else counter <= 5'd0; end end //Output Logic assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); assign aaah = (state == FALL_L || state == FALL_R); assign digging = (state == DIG_L || state == DIG_R); endmodule ``` 本題關鍵在於,觀察error錯誤波形會發現提示的cycle根本不足20,所以可以推斷其實前面可能有很長很長的一段(ground == 0),這裡計數器要設的大一點或者是設計一個state來鎖住counter>20後 再碰到地板會splat的結果。reg預設是unsigned 但還是會因為 11111 + 1 -> 100000,然後捨去高位bits,保留低5位導致計數錯誤。 ```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 ); reg [2:0] state, next_state; parameter LEFT = 3'b000, RIGHT = 3'b001, FALL_RIGHT = 3'b010, FALL_LEFT = 3'b011, DIG_RIGHT = 3'b100, DIG_LEFT = 3'b101, SPLAT = 3'b110; // **新增 SPLAT 狀態** reg [4:0] fall_counter; // 記錄掉落時鐘數 (最多 31 cycles) // 改成32bit就可以了:))) // **狀態轉移邏輯** always @(*) begin case (state) LEFT: begin if (!ground) next_state = FALL_LEFT; else if (dig) next_state = DIG_LEFT; else if (bump_left) next_state = RIGHT; else next_state = LEFT; end RIGHT: begin if (!ground) next_state = FALL_RIGHT; else if (dig) next_state = DIG_RIGHT; else if (bump_right) next_state = LEFT; else next_state = RIGHT; end FALL_RIGHT: begin if (ground) next_state = (fall_counter >= 20) ? SPLAT : RIGHT; // ✅ **確保落地時才進 SPLAT** else next_state = FALL_RIGHT; end FALL_LEFT: begin if (ground) next_state = (fall_counter >= 20) ? SPLAT : LEFT; // ✅ **確保落地時才進 SPLAT** else next_state = FALL_LEFT; end DIG_RIGHT: begin if (!ground) next_state = FALL_RIGHT; else next_state = DIG_RIGHT; end DIG_LEFT: begin if (!ground) next_state = FALL_LEFT; else next_state = DIG_LEFT; end SPLAT: begin next_state = SPLAT; // **永遠停留在 SPLAT 狀態** end default: next_state = LEFT; endcase end // **時序邏輯:狀態轉移與計數器** always @(posedge clk or posedge areset) begin if (areset) begin state <= LEFT; fall_counter <= 0; end else begin state <= next_state; if (state == FALL_LEFT || state == FALL_RIGHT) fall_counter <= fall_counter + 1; else fall_counter <= 0; // **落地時,重置計數器** end end // **輸出邏輯** assign walk_left = (state == LEFT) && (state != SPLAT); assign walk_right = (state == RIGHT) && (state != SPLAT); assign aaah = (state == FALL_RIGHT || state == FALL_LEFT); assign digging = (state == DIG_RIGHT || state == DIG_LEFT); endmodule ``` ### Fsm onehot ```verilog= module top_module( input in, input [9:0] state, output [9:0] next_state, output out1, output out2); always@(*)begin next_state[0] <= (state[0]&!in)||(state[1]&!in)||(state[2]&!in)||(state[3]&!in)||(state[4]&!in)||(state[7]&!in)||(state[8]&!in)||(state[9]&!in); next_state[1] <= (state[0]&in)||(state[8]&in)||(state[9]&in); next_state[2] <= (state[1]&in); next_state[3] <= (state[2]&in); next_state[4] <= (state[3]&in); next_state[5] <= (state[4]&in); next_state[6] <= (state[5]&in); next_state[7] <= (state[6]&in)||(state[7]&in); next_state[8] <= (state[5]&!in); next_state[9] <= (state[6]&!in); end assign out1 = state[8] || state[9]; assign out2 = state[7] || state[9]; endmodule ``` ### Fsm ps2 ```verilog= module top_module( input clk, input [7:0] in, input reset, // Synchronous reset output done ); parameter S1 = 0, S2 = 1, S3 = 2, DONE = 3; reg[2:0] state ; reg[2:0] next ; // State transition logic (combinational) always@(*)begin case(state) S1: next = in[3] ? S2: S1; S2: next = S3; S3: next = DONE; DONE : next = in[3] ? S2: S1; endcase end // State flip-flops (sequential) always@(posedge clk, posedge reset)begin if (reset) state <= S1; else state <= next; end // Output logic assign done = (state == DONE)? 1 : 0; endmodule ``` ### Fsm ps2data ```verilog= module top_module( input clk, input [7:0] in, input reset, // Synchronous reset output [23:0] out_bytes, output done ); // FSM from fsm_ps2 parameter S1 = 0, S2 = 1, S3 = 2, DONE = 3; reg[2:0] state ; reg[2:0] next ; reg[23:0] out_bytes_reg; // State transition logic (combinational) always@(*)begin case(state) S1: next = in[3] ? S2: S1; S2: next = S3; S3: next = DONE; DONE : next = in[3] ? S2: S1; default : next = S1; endcase end // State flip-flops (sequential) always@(posedge clk)begin if (reset) state <= S1; else state <= next; end always@(posedge clk)begin if (next== S2) begin if (state == S1)begin out_bytes_reg[23:16] <= in; end else if (state == DONE) begin out_bytes_reg[23:16] <= in; end end end always@(posedge clk)begin if(next == S3)begin out_bytes_reg[15:8] <= in; end end always@(posedge clk)begin if(next == DONE)begin out_bytes_reg[7:0] <= in; end end // New: Datapath to store incoming bytes. assign done = (state == DONE); assign out_bytes = done ? out_bytes_reg : 0; endmodule ``` ### Fsm serial ```verilog= module top_module( input clk, input in, input reset, // Synchronous reset output done ); parameter IDLE = 0, START = 1, S1 = 2, S2 = 3, S3 = 4, S4 = 5, S5 = 6, S6 = 7, S7 = 8, S8 = 9, STOP = 10, WAIT = 11; reg [3:0] state ; reg [3:0] next ; always@(*)begin case(state) IDLE : next = in? IDLE : START; START : next = S1; S1 : next = S2; S2 : next = S3; S3 : next = S4; S4 : next = S5; S5 : next = S6; S6 : next = S7; S7 : next = S8; S8 : next = in ? STOP : WAIT; WAIT : next = in ? IDLE : WAIT; STOP : next = in ? IDLE : START; default next = IDLE; endcase end always@(posedge clk)begin if(reset)begin state <= IDLE; end else begin state <= next; end end assign done = (state == STOP); endmodule ``` ## shift register(移位暫存器) ### Lfsr5 ![image](https://hackmd.io/_uploads/SJvBmoUjJg.png) ```verilog= module top_module( input clk, input reset, // Active-high synchronous reset to 5'h1 output [4:0] q ); always@(posedge clk)begin if (reset)begin q <= 5'd1; // 11111 end else begin q[4] <= q[0];// q[0] ^ 0的簡化 q[3] <= q[4]; q[2] <= q[3] ^ q[0]; q[1] <= q[2]; q[0] <= q[1]; end end endmodule ``` ### Mt2015 lfsr ![image](https://hackmd.io/_uploads/BJLPwc8oyx.png) ```verilog= module top_module ( input [2:0] SW, // R input [1:0] KEY, // L and clk output reg [2:0] LEDR // Q: 改為 reg 型態 ); wire d1, d2, d3; reg [2:0] q; // 改為 reg 型態 assign d1 = KEY[1] ? SW[0] : q[2]; assign d2 = KEY[1] ? SW[1] : q[0]; assign d3 = KEY[1] ? SW[2] : q[2]^q[1]; // 這個 always 塊可以用阻塞賦值,因為它是純粹的組合邏輯 always @(*) begin LEDR[0] = q[0]; LEDR[1] = q[1]; LEDR[2] = q[2]; end always @(posedge KEY[0]) begin q[0] <= d1; q[1] <= d2; q[2] <= d3; end endmodule ``` 以下這個版本可讀性較佳,把組合跟序向電路分開來撰寫 [參考來源](https://blog.csdn.net/wangkai_2019/article/details/106290065#3.2.3.4%205-bit%20LFSR%EF%BC%88Lfsr5%EF%BC%89) ```verilog= module top_module ( input [2:0] SW, // R input [1:0] KEY, // L and clk output [2:0] LEDR // Q ); reg[2:0] LEDR_next; always@(*)begin if (KEY[1])begin LEDR_next = SW; end else begin LEDR_next[0] = LEDR[2]; LEDR_next[1] = LEDR[0]; LEDR_next[2] = LEDR[2] ^ LEDR[1]; end end always@(posedge KEY[0]) begin LEDR <= LEDR_next; end endmodule ``` ### Lfsr32 設計圖可以參考 [lfsr5](https://hackmd.io/qtU92XTvTp6vxNMlP9IiLw#Lfsr5) ```verilog= module top_module( input clk, input reset, // Active-high synchronous reset to 32'h1 output [31:0] q ); reg[31:0] q_next; always@(*) begin q_next = {q[0], q[31:1]}; q_next[21] = q[0] ^ q[22]; q_next[1] = q[0] ^ q[2]; q_next[0] = q[0] ^ q[1]; end always@(posedge clk)begin if (reset)begin q <= 32'd1; end else begin q <= q_next; end end endmodule ``` ## Mealy Machine (米利狀態機) 米利型有限狀態機(英語:Mealy machine)是基於它的當前狀態和輸入生成輸出的有限狀態自動機(更精確的叫有限狀態變換器)。這意味著它的狀態圖將為每個轉移邊包括輸入和輸出二者。 白話來說 mealy machine 『輸出output』要依靠「狀態state」+「輸入input」來決定 moore machine 『輸出output』由「狀態state」決定。 ``` S0 + input1 -> S1, S2 S0 + input1 -> S3 ``` ### Exams/ece241 2013 q8 ```verilog= module top_module ( input clk, input aresetn, // Asynchronous active-low reset input x, output z ); parameter S0 = 0, S1 = 1, S2 = 2; reg [1:0] state; reg [1:0] next; //注意狀態轉移階段跟摩爾型的差異 always@(*)begin case(state) S0 :begin next = x ? S1 : S0; // x end S1 :begin next = x ? S1 : S2; // 1x, x = 1 -> S1 , x = 0 -> S2 end S2 : begin next = x ? S1: S0; //10 end endcase end always@(posedge clk, negedge aresetn)begin if (aresetn == 1'b0) begin state <= S0; end else begin state <= next; end end always@(*)begin case(state) S0 : z = 1'b0; S1 : z = 1'b0; S2 : z = x; // S2 是 10 所以要結合x來判斷是否輸出1 endcase end endmodule ``` ### [Exams/ece241 2014 q5b](https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q5b) 二補數算法 Mealy FSM ```verilog= module top_module ( input clk, input areset, input x, output z ); parameter A = 0, B = 1; reg state, next; always@(*)begin case(state) A : next = x? B : A; B : next = B; endcase end always@(posedge clk, posedge areset)begin if (areset)begin state <= A; end else begin state <= next; end end always@(*)begin z = (!state&&x)||(state&&!x); end endmodule ``` ### [Exams/ece241 2014 q5a](https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q5a) [二補數算法](https://zh.wikipedia.org/zh-tw/%E4%BA%8C%E8%A3%9C%E6%95%B8#:~:text=\)-,%E6%96%B9%E6%B3%95%E4%BA%8C,-%5B%E7%B7%A8%E8%BC%AF%5D) 本題使用3個狀態的摩爾電路解題 **STATE_A** 若該位元為0,將二補數對應位元填0,繼續檢查下一位元(較高的位元),直到找到1然後進入SB。 **STATE_B** 此狀態輸出1,因為前一個input是0,或是剛從SA轉移過來。根據輸入`1 -> SC , 0 -> SB`。 **STATE_C** 此狀態輸出0,因為前一個input是1。根據輸入 `1 -> SC , 0 -> SB`。 ```verilog= module top_module ( input clk, input areset, input x, output z ); parameter A = 2'd0, B = 2'd1, C = 2'd2; reg [1:0] current_state; reg [1:0] next_state; always@(*)begin case(current_state) A:begin next_state = x ? B : A; end B:begin next_state = x ? C : B; end C:begin next_state = x ? C : B; end default:begin next_state = A; end endcase end always@(posedge clk or posedge areset)begin if(areset)begin current_state <= A; end else begin current_state <= next_state; end end assign z = current_state == B; endmodule ``` ### Exams/2014 q3fsm ```verilog module top_module ( input clk, input reset, // Synchronous reset input s, input w, output z ); parameter A = 0, B = 1; reg state; reg next; // 組合電路 -> 判斷 State always@(*)begin case(state) A : next = s? B :A; B : next = B; default: next = A; endcase end always@(posedge clk)begin if (reset)begin state <= A; end else begin state <= next; end end reg [1:0]Count; reg [1:0]Time; always@(posedge clk)begin if (reset || state == A) begin Count <= 0; Time <= 0; z <= 0; end else if (state == B)begin if (Time < 2) begin Time <= Time + 1; Count <= Count + (w ? 1 : 0); z <= 0; end else begin if ((Count + (w ? 1 : 0)) == 2) z <= 1; else begin z <= 0; end Time <= 0; Count <= 0; end end end endmodule ``` ### [Exams/2014 q3b](https://hdlbits.01xz.net/wiki/Exams/2014_q3bfsm) ```verilog= module top_module ( input clk, input reset, // Synchronous reset input x, output z ); parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4; reg [2:0] state, next; always@(*)begin case(state) S0 : next = x? S1 : S0; S1 : next = x? S4 : S1; S2 : next = x? S1 : S2; S3 : next = x? S2 : S1; S4 : next = x? S4 : S3; default : next = S0; endcase end always@(posedge clk)begin if (reset)begin state <= S0; end else begin state <= next; end end assign z = (state == S3 || state == S4) ; endmodule ``` ## 其他 ### Synchronous FIFO 來源 : [VL46 同步FIFO](https://www.nowcoder.com/practice/3ece2bed6f044ceebd172a7bf5cfb416?tpId=302&tqId=5000603&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3DVerilog%25E7%25AF%2587%26topicId%3D302) ![image](https://hackmd.io/_uploads/r1S_G2ghyg.png) [FPGA数字IC的Verilog刷题进阶版22-同步FIFO](https://www.bilibili.com/video/BV1S5411d7Vq/?spm_id_from=333.788&vd_source=ee346ab269e4eba3052dfd39001b45f7) [笔试 | 同步FIFO设计详解及代码分享(这一篇就足够~)](https://mp.weixin.qq.com/s/WguYBqXZzsfJ4eSI6ROn9g) [FPGA数字IC芯片设计求职必备-同步FIFO详解](https://www.bilibili.com/video/BV1Du411z7gN?spm_id_from=333.788.videopod.sections&vd_source=ee346ab269e4eba3052dfd39001b45f7) ```verilog= `timescale 1ns/1ns /**********************************RAM************************************/ module dual_port_RAM #(parameter DEPTH = 16, parameter WIDTH = 8)( input wclk, input wenc, input [$clog2(DEPTH)-1:0] waddr // 深度對2取對數,得到位址的位寬。 ,input [WIDTH-1:0] wdata // 資料寫入 ,input rclk, input renc, input [$clog2(DEPTH)-1:0] raddr // 深度對2取對數,得到位址的位寬。 ,output reg [WIDTH-1:0] rdata // 資料輸出 ); reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1]; always @(posedge wclk) begin if(wenc) RAM_MEM[waddr] <= wdata; end always @(posedge rclk) begin if(renc) rdata <= RAM_MEM[raddr]; end endmodule /**********************************SFIFO************************************/ module sfifo#( parameter WIDTH = 8, parameter DEPTH = 16 )( input clk, input rst_n, input winc, input rinc, input [WIDTH-1:0] wdata, output reg wfull, output reg rempty, output wire [WIDTH-1:0] rdata ); localparam ADDR_WIDTH = $clog2(DEPTH); reg [ADDR_WIDTH:0] waddr; reg [ADDR_WIDTH:0] raddr; always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin waddr <= 'b0; end else begin if(winc && ~wfull) begin waddr <= waddr + 1'b1; end else begin waddr <= waddr; end end end always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin raddr <= 'b0; end else begin if(rinc && ~rempty) begin raddr <= raddr + 1'b1; end else begin raddr <= raddr; end end end // assign wfull = (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]}); // assign rempty = (raddr == waddr); always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin wfull <= 'b0; rempty <= 'b0; end else begin wfull <= (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]}); rempty <= (raddr == waddr); end end // RAM例化,注意讀寫使能端的訊號 dual_port_RAM #( .DEPTH(DEPTH), .WIDTH(WIDTH) ) dual_port_RAM_U0 ( .wclk(clk), .wenc(winc && ~wfull), .waddr(waddr[ADDR_WIDTH-1:0]), // 深度對2取對數,得到位址的位寬。 .wdata(wdata), // 資料寫入 .rclk(clk), .renc(rinc && ~rempty), .raddr(raddr[ADDR_WIDTH-1:0]), // 深度對2取對數,得到位址的位寬。 .rdata(rdata) // 資料輸出 ); endmodule ``` ### Asynchronous FIFO ```verilog `timescale 1ns/1ns /******** 雙埠RAM (Dual Port RAM) ***********/ module dual_port_RAM #( parameter DEPTH = 16, // 記憶體深度 parameter WIDTH = 8 // 資料寬度 )( input wclk, // 寫入時脈 input wenc, // 寫入使能 input [$clog2(DEPTH)-1:0] waddr, // 寫入位址(以記憶體深度取對數決定位寬) input [WIDTH-1:0] wdata, // 寫入資料 input rclk, // 讀取時脈 input renc, // 讀取使能 input [$clog2(DEPTH)-1:0] raddr, // 讀取位址(以記憶體深度取對數決定位寬) output reg [WIDTH-1:0] rdata // 讀出資料 ); // 宣告一個記憶體陣列,大小為 DEPTH,每個單元寬度為 WIDTH reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1]; // 寫入操作:在 wclk 上升沿,若寫入使能有效則將資料寫入指定位址 always @(posedge wclk) begin if (wenc) RAM_MEM[waddr] <= wdata; end // 讀取操作:在 rclk 上升沿,若讀取使能有效則從指定位址讀出資料 always @(posedge rclk) begin if (renc) rdata <= RAM_MEM[raddr]; end endmodule /******** 非同步 FIFO (Asynchronous FIFO) *********/ /********************************************** * 說明: 非同步 FIFO 用於在不同時脈域間傳遞資料, * 因寫入與讀取時脈可能不同,故需特殊同步機制。 **********************************************/ module asyn_fifo #( parameter WIDTH = 8, // FIFO 資料寬度 parameter DEPTH = 16 // FIFO 深度(可儲存資料個數) )( input wclk, // 寫入時脈 input rclk, // 讀取時脈 input wrstn, // 寫入時脈域非同步低有效復位 input rrstn, // 讀取時脈域非同步低有效復位 input winc, // 寫入增量訊號(嘗試寫入) input rinc, // 讀取增量訊號(嘗試讀取) input [WIDTH-1:0] wdata, // 寫入資料 output wire wfull, // FIFO 滿的標誌 output wire rempty, // FIFO 空的標誌 output wire [WIDTH-1:0] rdata // 讀出資料 ); // 位址位寬,由 FIFO 深度決定(取對數後進位) localparam ADDR_WIDTH = $clog2(DEPTH); // 寫入與讀取二進位計數器(多一位用於區分循環) reg [ADDR_WIDTH:0] waddr; reg [ADDR_WIDTH:0] raddr; // 寫入計數器:在 wclk 上升沿或 wrstn 低電平時更新 always @ (posedge wclk or negedge wrstn) begin if (~wrstn) begin waddr <= 'b0; end else begin if (winc && ~wfull) begin waddr <= waddr + 1'b1; end else begin waddr <= waddr; end end end // 讀取計數器:在 rclk 上升沿或 rrstn 低電平時更新 always @ (posedge rclk or negedge rrstn) begin if (~rrstn) begin raddr <= 'b0; end else begin if (rinc && ~rempty) begin raddr <= raddr + 1'b1; end else begin raddr <= raddr; end end end // 將二進位位址轉換成格雷碼,降低跨時脈同步時的錯誤機率 wire [ADDR_WIDTH:0] waddr_gray; wire [ADDR_WIDTH:0] raddr_gray; assign waddr_gray = waddr ^ (waddr >> 1); assign raddr_gray = raddr ^ (raddr >> 1); // 在寫入時脈域內暫存轉換後的格雷碼(waddr_gray_reg) reg [ADDR_WIDTH:0] waddr_gray_reg; always @ (posedge wclk or negedge wrstn) begin if (~wrstn) begin waddr_gray_reg <= 'd0; end else begin waddr_gray_reg <= waddr_gray; end end // 在讀取時脈域內暫存轉換後的格雷碼(raddr_gray_reg) reg [ADDR_WIDTH:0] raddr_gray_reg; always @ (posedge rclk or negedge rrstn) begin if (~rrstn) begin raddr_gray_reg <= 'd0; end else begin raddr_gray_reg <= raddr_gray; end end // 將讀取時脈域的格雷碼同步到寫入時脈域(兩級同步器) reg [ADDR_WIDTH:0] addr_r2w_t; reg [ADDR_WIDTH:0] addr_r2w; always @ (posedge wclk or negedge wrstn) begin if (~wrstn) begin addr_r2w_t <= 'd0; addr_r2w <= 'd0; end else begin addr_r2w_t <= raddr_gray_reg; addr_r2w <= addr_r2w_t; end end // 將寫入時脈域的格雷碼同步到讀取時脈域(兩級同步器) reg [ADDR_WIDTH:0] addr_w2r_t; reg [ADDR_WIDTH:0] addr_w2r; always @ (posedge rclk or negedge rrstn) begin if (~rrstn) begin addr_w2r_t <= 'd0; addr_w2r <= 'd0; end else begin addr_w2r_t <= waddr_gray_reg; addr_w2r <= addr_w2r_t; end end // 判斷 FIFO 滿的條件: // 當寫入時脈域的格雷碼(waddr_gray_reg)與同步過來的讀取位址(addr_r2w), // 經過最高位反轉後相等,表示寫指標已超前一個循環 => FIFO 滿 assign wfull = (waddr_gray_reg == {~addr_r2w[ADDR_WIDTH:ADDR_WIDTH-1], addr_r2w[ADDR_WIDTH-2:0]}); // 判斷 FIFO 空的條件: // 當讀取時脈域的格雷碼(raddr_gray_reg)與同步過來的寫指標(addr_w2r)相等,表示 FIFO 空 assign rempty = (raddr_gray_reg == addr_w2r); // 例化雙埠RAM作為 FIFO 的資料儲存單元 dual_port_RAM #( .DEPTH(DEPTH), .WIDTH(WIDTH) ) dual_port_RAM_U0 ( .wclk(wclk), .wenc(winc && ~wfull), .waddr(waddr[ADDR_WIDTH-1:0]), // 僅使用低位作為 RAM 的位址 .wdata(wdata), // 寫入資料 .rclk(rclk), .renc(rinc && ~rempty), .raddr(raddr[ADDR_WIDTH-1:0]), // 僅使用低位作為 RAM 的位址 .rdata(rdata) // 讀出資料 ); endmodule ``` ### 簡易秒表 [本題來源](https://www.nowcoder.com/practice/6493ca8c7b67499f918e1fa33b4cdeda?tpId=302&tqId=5000633&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3DVerilog%25E7%25AF%2587%26topicId%3D302) ```verilog= `timescale 1ns/1ns // 正確 module count_module( input clk, input rst_n, output reg [5:0]second, output reg [5:0]minute ); always@(posedge clk, negedge rst_n)begin if (~rst_n)begin minute <= 0; second <= 0; end else if (minute == 6'd60) begin minute <= minute; second <= second; end else if (second == 6'd60) begin second <= 6'd1; minute <= minute + 1; end else begin second <= second + 1; end end endmodule ``` ```verilog= //錯誤寫法 // `timescale 1ns/1ns module count_module( input clk, input rst_n, output reg [5:0]second, output reg [5:0]minute ); reg [5:0]min; reg [5:0]sec; always@(posedge clk, negedge rst_n)begin if (~rst_n)begin min <= 0; sec <= 0; end else if (min == 6'd60) begin min <= min; sec <= sec; end else if (sec == 6'd60) begin sec <= 6'd1; min <= min + 1; end else begin sec <= sec + 1; end minute <= min;// 這裡使用non-blocking assign 會抓到前一個時脈的值而不是更新後的答案 second <= sec;// 這裡使用non-blocking assign 會抓到前一個時脈的值而不是更新後的答案 end endmodule ``` ### 單端口RAM [VL53 单端口RAM](https://www.nowcoder.com/practice/a1b0c13edba14a2984e7369d232d9793?tpId=302&tqId=5000609&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3DVerilog%25E7%25AF%2587%26topicId%3D302) ```verilog= `timescale 1ns/1ns module RAM_1port( input clk, input rst, input enb, input [6:0]addr, input [3:0]w_data, output wire [3:0]r_data ); //*************code***********// reg [3:0] ram[127:0]; //reg [3:0] ram_data; integer i; always@(posedge clk, negedge rst)begin if (~rst)begin for(i=0 ; i < 128 ; i =i +1)begin ram[i] <= 0; end end else begin if (enb)begin ram[addr] <= w_data; end end end assign r_data = enb? 4'b0 : ram[addr]; //*************code***********// endmodule ``` ### 多bit MUX同步器 ```verilog= `timescale 1ns/1ns module mux( input clk_a, // clk_a 時鐘域 input clk_b, // clk_b 時鐘域 input arstn, // 非同步重置訊號,低有效 (用於 clk_a 時鐘域) input brstn, // 非同步重置訊號,低有效 (用於 clk_b 時鐘域) input [3:0] data_in, // 4 位元資料輸入訊號 input data_en, // 資料使能訊號 output reg [3:0] dataout // 4 位元資料輸出訊號 ); // clk_a 時鐘域中對 data_en 訊號進行寄存 reg data_en_a_reg; always @ (posedge clk_a or negedge arstn) begin if (~arstn) begin data_en_a_reg <= 1'b0; // 非同步重置時將寄存器歸零 end else begin data_en_a_reg <= data_en; // 在 clk_a 時鐘上取樣 data_en 訊號 end end // clk_a 時鐘域中對 data_in 訊號進行寄存 reg [3:0] data_in_a_reg; always @ (posedge clk_a or negedge arstn) begin if (~arstn) begin data_in_a_reg <= 4'b0; // 非同步重置時將寄存器歸零 end else begin data_in_a_reg <= data_in; // 在 clk_a 時鐘上取樣 data_in 訊號 end end // 在 clk_b 時鐘域中,利用雙級同步器同步來自 clk_a 域的 data_en 訊號 reg data_en_b_t; reg data_en_b; always @ (posedge clk_b or negedge brstn) begin if (~brstn) begin data_en_b_t <= 1'b0; // 非同步重置時清零 data_en_b <= 1'b0; // 非同步重置時清零 end else begin data_en_b_t <= data_en_a_reg; // 第一級取樣來自 clk_a 時鐘域的 data_en 訊號 data_en_b <= data_en_b_t; // 第二級取樣,降低亞穩態風險 end end // 在 clk_b 時鐘域中,根據同步後的 data_en 訊號控制資料輸出 always @ (posedge clk_b or negedge brstn) begin if (~brstn) begin dataout <= 4'b0; // 非同步重置時清零資料輸出 end else begin if (data_en_b) dataout <= data_in_a_reg; // 當使能訊號有效時,將 clk_a 時鐘域取樣到的資料輸出 else dataout <= dataout; // 否則保持目前輸出狀態 end end endmodule ``` ### RAM簡單實現 [來源](https://www.nowcoder.com/practice/2c17c36120d0425289cfac0855c28796?tpId=302&tqId=5000627&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page) ```verilog= `timescale 1ns/1ns module ram_mod( input clk, input rst_n, input write_en, input [7:0]write_addr, input [3:0]write_data, input read_en, input [7:0]read_addr, output reg [3:0]read_data ); reg [3:0] ram[7:0]; integer i; //write always@(posedge clk, negedge rst_n)begin if (!rst_n) begin for (i = 0 ; i < 128 ; i = i + 1)begin ram[i] <= 4'b000; end end else if (write_en)begin ram[write_addr] <= write_data; end end //read always@(posedge clk, negedge rst_n)begin if (!rst_n)begin read_data <= 4'b000; end else if (read_en) begin read_data <= ram[read_addr]; end end endmodule ``` ### 數據累加輸出 [來源](https://www.nowcoder.com/practice/956fa4fa03e4441d85262dc1ec46a3bd?tpId=302&tqId=5000601&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3DVerilog%25E7%25AF%2587%26topicId%3D302) 熟悉valid/ready設計觀念 : [流水线中的valid-ready握手控制打拍](https://zhuanlan.zhihu.com/p/620498057) ```verilog= `timescale 1ns/1ns module valid_ready( input clk , input rst_n , input [7:0] data_in , input valid_a , input ready_b , output ready_a , output reg valid_b , output reg [9:0] data_out ); reg [1:0] count; //計數區塊 always@(posedge clk, negedge rst_n)begin if (!rst_n)begin count <= 2'b00; end else begin if (valid_a & ready_a)begin if (count == 2'd3) count <= 2'd0; else count <= count + 1 ; end end end //累加區塊 always@(posedge clk, negedge rst_n)begin if (!rst_n)begin data_out <= 10'b0; end else begin if (valid_a & ready_a)begin if(count == 2'd0) begin data_out <= data_in; end else begin data_out <= data_out + data_in; end end end end // 對下游輸出valid_b指示信號 always@(posedge clk, negedge rst_n)begin if (!rst_n)begin valid_b <= 1'b0; end else begin // 當累加計數器達到3,且此時有 valid_a 與 ready_a 為有效狀態時, // 代表已完成四次資料累加,輸出結果有效,因此將 valid_b 設為 1。 if (count == 2'd3 && valid_a && ready_a)begin valid_b <= 1'b1; // 累加完成,設定輸出數據有效 (valid_b = 1) end // 當輸出有效 (valid_b 為 1) 且下游已準備好接收資料 (ready_b 為 1) 時, // 表示資料已被下游接收,因此將 valid_b 清零以便開始下一輪累加。 else if (valid_b && ready_b) begin valid_b <= 1'b0; // 下游已接收,清除輸出有效旗標 (valid_b = 0) end // 其他情況下,保持 valid_b 的原狀態不變。 else begin valid_b <= valid_b; // 保持目前狀態,不做改變 end end end assign ready_a = !valid_b | ready_b; // 如果ready_a : 代表下一個clk posedge 就會通過 line52 的判斷 endmodule ``` ```verilog=67 //解釋 assign ready_a = !valid_b | ready_b; ``` * 當 valid_b 為低(0)時,表示目前模組還沒有累加完成一組資料,輸出資料尚未有效,此時模組可以持續接受上游輸入的資料,所以 ready_a 為高(1)。 * 當 valid_b 為高(1)時,表示已累加好一組資料且輸出有效,但如果下游的 ready_b 為高(1),表示下游已準備好接收該筆資料,那麼模組便可以接收新的資料,因此 ready_a 也會為高。 總結來說,這行的邏輯確保了: * 若累加結果尚未準備好(valid_b = 0),模組能夠持續接受資料。 * 若累加結果已準備好(valid_b = 1),則只有當下游接收了資料(ready_b = 1)後,模組才會接受新資料。 #### 相關閱讀 1. [skid buffer](https://blog.csdn.net/weixin_42415266/article/details/126291919) 2. [Half-Buffer与Skid-Buffer介绍及其在流水线中的应用](https://fpga.eetrend.com/blog/2024/100581076.html) 3. [FPGACPU.CA](https://fpgacpu.ca/index.html) ### 狀態機非重疊檢測 [來源](https://www.nowcoder.com/practice/2e35c5c0798249aaa2e1044dbaf218f2?tpId=302&tqId=5000610&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3DVerilog%25E7%25AF%2587%26topicId%3D302) ```verilog `timescale 1ns/1ns module sequence_test1( input wire clk , input wire rst , input wire data , output reg flag ); //*************code***********// reg[4:0] state, next; always@(*)begin case(state) 5'd0: next = data? 1 : 0; // 5'd1: next = data? 1 : 2; // 1 5'd2: next = data? 3 : 0; // 10 5'd3: next = data? 4 : 2; // 101 5'd4: next = data? 5 : 2; // 1011 5'd5: next = data? 1 : 0; // 10111 default: next = 0; endcase end always @(posedge clk or negedge rst) begin if (!rst) state <= 0; else state <= next; end always @(posedge clk or negedge rst) begin if (!rst) flag <= 1'b0; else begin if(state == 4 && data == 1'b1) begin flag <= 1'b1; end else begin flag <= 1'b0; end end end //*************code***********// endmodule ``` #### 錯誤檢討 以下寫法會延遲一個clock後輸出(moore machine)。雖然題目沒有明確表達,題目希望是使用mealy machine也就是在 1011時就要立刻根據輸入判斷,所以不可以延遲一個時脈輸出。 但以下這個寫法會是moore machine 所以會延遲輸出。 ![image](https://hackmd.io/_uploads/HyUDPK421e.png) ```verilog= `timescale 1ns/1ns module sequence_test1( input wire clk , input wire rst , input wire data , output reg flag ); //*************code***********// reg[3:0] state, next; always@(*)begin if (!rst)begin next = 0; end else begin case(state) 4'd0: next = data? 1 : 0; // 4'd1: next = data? 1 : 2; // 1 4'd2: next = data? 3 : 0; // 10 4'd3: next = data? 4 : 2; // 101 4'd4: next = data? 5 : 2; // 1011 4'd5: next = data? 1 : 0; // 10111 default: next = 0; endcase end end always @(posedge clk, negedge rst)begin if (!rst) state <= 0; else state <= next; end always @(posedge clk or negedge rst) begin if (!rst) flag <= 1'b0; else //moore machine flag <= (state == 4'd5) ? 1'b1 : 1'b0; end //*************code***********// endmodule ``` ### 重疊序列檢測 [來源](https://www.nowcoder.com/practice/10be91c03f5a412cb26f67dbd24020a9?tpId=302&tqId=5000611&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page) 用摩爾狀態機(moore machine) ```verilog= `timescale 1ns/1ns module sequence_test2( input wire clk, input wire rst, input wire data, output reg flag ); //*************code***********// // Moore machine reg[3:0] state, next; always@(*)begin if (!rst)begin next = 0; end else begin case(state) 4'd0: next = data? 1 : 0; // 4'd1: next = data? 1 : 2; // 1 4'd2: next = data? 3 : 0; // 10 4'd3: next = data? 4 : 2; // 101 4'd4: next = data? 1 : 2; // 1011 default: next = 0; endcase end end always @(posedge clk, negedge rst)begin if (!rst) state <= 0; else state <= next; end always @(posedge clk or negedge rst) begin if (!rst) flag <= 1'b0; else //moore machine flag <= (state == 4'd4) ? 1'b1 : 1'b0; end //*************code***********// endmodule ``` ### VL60 使用握手信号实现跨时钟域数据传输 [來源](https://www.nowcoder.com/practice/2bf1b28a4e634d1ba447d3495134baac?tpId=311&tqId=5000697&sourceUrl=%2Fexam%2Foj%3FquestionJobId%3D10%26subTabName%3Donline_coding_page) 參考資料 1. [【牛客】VL60 使用握手信号实现跨时钟域数据传输](https://blog.csdn.net/qq_45434284/article/details/136400889) 2. [【数字IC】_跨时钟域专题_01_概念、亚稳态、同步时钟](https://www.bilibili.com/video/BV1YYDLYPEuM?spm_id_from=333.788.videopod.sections&vd_source=ee346ab269e4eba3052dfd39001b45f7) ``` ``` ### Exams/ece241 2013 q4 ![image](https://hackmd.io/_uploads/SJaxmwr3kx.png) ```verilog= module top_module ( input clk, input reset, input [3:1] s, output fr3, output fr2, output fr1, output dfr ); reg[3:0] p_state, n_state; parameter A = 4'b0000, B0 = 4'b0010, B1 = 4'b0011, C0 = 4'b0110, C1 = 4'b0111, D = 4'b1111; always @(posedge clk) begin if (reset) begin {dfr,fr3,fr2,fr1} <= 4'b1111; p_state <= A; end else begin case(p_state) A: if(s==1) n_state = B0; else if(s==3) n_state = C0; else if(s==7) n_state = D; else n_state = A; B0: if(s==0) n_state = A; else if(s==3) n_state = C0; else if(s==7) n_state = D; else n_state = B0; B1: if(s==0) n_state = A; else if(s==3) n_state = C0; else if(s==7) n_state = D; else n_state = B1; C0: if(s==0) n_state = A; else if(s==1) n_state = B1; else if(s==7) n_state = D; else n_state = C0; C1: if(s==0) n_state = A; else if(s==1) n_state = B1; else if(s==7) n_state = D; else n_state = C1; D: if(s==0) n_state = A; else if(s==1) n_state = B1; else if(s==3) n_state = C1; else n_state = D; endcase p_state = n_state; case (p_state) A: {dfr,fr3,fr2,fr1} = 4'b1111; B0: {dfr,fr3,fr2,fr1} = 4'b0011; B1: {dfr,fr3,fr2,fr1} = 4'b1011; C0: {dfr,fr3,fr2,fr1} = 4'b0001; C1: {dfr,fr3,fr2,fr1} = 4'b1001; D: {dfr,fr3,fr2,fr1} = 4'b0000; endcase end end endmodule ``` ```verilog= //優化解provided by 俊廷 module top_module ( input clk, input reset, input [3:1] s, output fr3, output fr2, output fr1, output dfr ); reg[3:0] p_state, n_state; parameter A = 4'b0000, B0 = 4'b0010, B1 = 4'b0011, C0 = 4'b0110, C1 = 4'b0111, D = 4'b1111; always @(posedge clk) begin if (reset) begin {dfr,fr3,fr2,fr1} <= 4'b1111; p_state <= A; end else begin case(p_state) A: if(s==1) n_state = B0; else n_state = A; B0: if(s==0) n_state = A; else if(s==3) n_state = C0; else n_state = B0; B1: if(s==0) n_state = A; else if(s==3) n_state = C0; else n_state = B1; C0: if(s==1) n_state = B1; else if(s==7) n_state = D; else n_state = C0; C1: if(s==1) n_state = B1; else if(s==7) n_state = D; else n_state = C1; D: if(s==3) n_state = C1; else n_state = D; endcase p_state = n_state; case (p_state) A: {dfr,fr3,fr2,fr1} = 4'b1111; B0: {dfr,fr3,fr2,fr1} = 4'b0011; B1: {dfr,fr3,fr2,fr1} = 4'b1011; C0: {dfr,fr3,fr2,fr1} = 4'b0001; C1: {dfr,fr3,fr2,fr1} = 4'b1001; D: {dfr,fr3,fr2,fr1} = 4'b0000; endcase end end endmodule ``` ## 參考資料 1. [10620王俊堯教授數位邏輯設計_第12講 Analysis of Clocked Sequential Circuits](https://youtu.be/8mKQ1LdztQo?si=5Tmz2BkVBfcghsDg) // 省時間可以看DE講即可 2. [Verilog刷题58道——FPGA数字IC笔试题、面试手撕代码](https://zhuanlan.zhihu.com/p/524916728)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully