跳轉到

HDLBits Tutorial

Getting Started⚓︎

Getting Started⚓︎

Website: https://hdlbits.01xz.net/wiki/Step_one

這題是教你怎麼操作平台的,然後要對one輸出1。這裡有個細節是給值時盡量寫的清楚一點,像這裡1bit,就可以不是只給1,而是給1'b1。

Verilog
module top_module( output one );
    assign one = 1'b1;
endmodule


Output Zero⚓︎

Website: https://hdlbits.01xz.net/wiki/Zero

這題跟上題大同小異,只是換成輸出0。

Verilog
module top_module(
    output zero
);// Module body starts after semicolon
    assign zero = 1'b0;
endmodule


Verilog Language⚓︎

Basics⚓︎

Simple wire⚓︎

Website: https://hdlbits.01xz.net/wiki/Wire

這題就是簡單的把out和in接在一起。

Verilog
module top_module( input in, output out );
    assign out = in;
endmodule


Four wires⚓︎

Website: https://hdlbits.01xz.net/wiki/Wire4

這題就照著圖接線,w和a相接,xy和b相接,z和c相接。

Verilog
module top_module( 
    input a,b,c,
    output w,x,y,z );
    assign w = a;
    assign x = b;
    assign y = b;
    assign z = c;
endmodule


Inverter⚓︎

Website: https://hdlbits.01xz.net/wiki/Notgate

這題要寫一個not gate。
值得注意的是,verilog中有分bitwise operator和logical operator,bitwise operator就是對input的每個bit都做相對的運算,所以最後輸出的bit數會跟input一樣。而logical operator只會邏輯上做運算,最後只會輸出1 bit。
所以說bitwise not符號是~,而logical not符號是!,雖然這題input只有1 bit沒差,不過細節可能要注意。

Verilog
module top_module( input in, output out );
    assign out = ~in;
endmodule


AND gate⚓︎

Website: https://hdlbits.01xz.net/wiki/Andgate

這題就刻一個and gate,跟上題差不多,要注意的是bitwise and符號是&,而logical and符號是&&

Verilog
module top_module( 
    input a, 
    input b, 
    output out );
    assign out = a & b;
endmodule


NOR gate⚓︎

Website: https://hdlbits.01xz.net/wiki/Norgate

這題就刻一個nor gate,跟上題差不多,要注意的是bitwise or符號是~,而logical and符號是~~

Verilog
module top_module( 
    input a, 
    input b, 
    output out );
    assign out = ~(a | b);
endmodule


XNOR gate⚓︎

Website: https://hdlbits.01xz.net/wiki/Xnorgate

這題就刻一個xnor gate,跟上題差不多,要注意的是bitwise xor符號是^,而verilog中沒有logical xor運算。

Verilog
module top_module( 
    input a, 
    input b, 
    output out );
    assign out = ~(a ^ b);
endmodule


Declaring wires⚓︎

Website: https://hdlbits.01xz.net/wiki/Wire_decl

這題引入了wire的概念,wire就是在線路複雜時,提供節點來幫助閱讀。補充一下,input和output本身就是wire。

Verilog
`default_nettype none
module top_module(
    input a,
    input b,
    input c,
    input d,
    output out,
    output out_n   ); 
    wire a_and_b, c_and_d;
    assign a_and_b = a & b;
    assign c_and_d = c & d;
    assign out = a_and_b | c_and_d;
    assign out_n = ~out;
endmodule


7458 chip⚓︎

Website: https://hdlbits.01xz.net/wiki/7458

這題跟上題類似,就是線路稍微複雜,可以直接寫,也可以使用wire幫助閱讀。

Verilog
module top_module ( 
    input p1a, p1b, p1c, p1d, p1e, p1f,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
    assign p1y = (p1a & p1b & p1c) | (p1d & p1e & p1f);
    assign p2y = (p2a & p2b) | (p2c & p2d);
endmodule


Vectors⚓︎

Vectors⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector0

這題是將[2:0] vec分別賦值給[2:0] outv和{o2,o1,o0},補充說明,assign {o2,o1,o0} = vec;等價於assign o2 = vec[2]; assign o1 = vec[1]; assign o0 = vec[0];

Verilog
module top_module ( 
    input wire [2:0] vec,
    output wire [2:0] outv,
    output wire o2,
    output wire o1,
    output wire o0  ); // Module body starts after module declaration
    assign outv = vec;
    assign {o2,o1,o0} = vec;
endmodule


Vectors in more detail⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector1

跟上題大同小異,assign {out_hi,out_lo} = in;等價於assign out_hi = in[15:8]; assign out_lo = in[7:0];

Verilog
`default_nettype none     // Disable implicit nets. Reduces some types of bugs.
module top_module( 
    input wire [15:0] in,
    output wire [7:0] out_hi,
    output wire [7:0] out_lo );
    assign {out_hi,out_lo} = in;
endmodule


Vector part select⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector2

跟上題大同小異,assign out = {in[7:0],in[15:8],in[23:16],in[31:24]};等價於assign out[31:24] = in[ 7: 0]; assign out[23:16] = in[15: 8]; assign out[15: 8] = in[23:16]; assign out[ 7: 0] = in[31:24];

Verilog
module top_module( 
    input [31:0] in,
    output [31:0] out );
    assign out = {in[7:0],in[15:8],in[23:16],in[31:24]};
endmodule


Bitwise operators⚓︎

Website: https://hdlbits.01xz.net/wiki/Vectorgates

這題主要講述bitwise operators和logical operators的差異。像說bitwise or的符號為|,logical or的符號為||,bitwise not的符號為~,logical not的符號為!。這題的not是bitwise not,不要弄混了。

Verilog
module top_module( 
    input [2:0] a,
    input [2:0] b,
    output [2:0] out_or_bitwise,
    output out_or_logical,
    output [5:0] out_not
);
    assign out_or_bitwise = a | b;
    assign out_or_logical = a || b;
    assign out_not = ~ {b,a};
endmodule


Four-input gates⚓︎

Website: https://hdlbits.01xz.net/wiki/Gates4

這題在複習各種gate的用法。

Verilog
module top_module( 
    input [3:0] in,
    output out_and,
    output out_or,
    output out_xor
);
    assign out_and = in[3] & in[2] & in[1] & in[0];
    assign out_or = in[3] | in[2] | in[1] | in[0];
    assign out_xor = in[3] ^ in[2] ^ in[1] ^ in[0];
endmodule

Vector concatenation operator⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector3

這題在教concatenation的概念,然後因為題目要求要padding11在最右邊2bits,所以要加上2'b11。

Verilog
module top_module (
    input [4:0] a, b, c, d, e, f,
    output [7:0] w, x, y, z );//

    assign {w,x,y,z} = {a,b,c,d,e,f,2'b11};

endmodule


Vector reversal 1⚓︎

Website: https://hdlbits.01xz.net/wiki/Vectorr

這題當然能用concatenation的概念完成,當然如果想寫個類似for loop的方法連線,可以參考generate語法。

Verilog
module top_module( 
    input [7:0] in,
    output [7:0] out
);
    generate
        genvar i;
        for (i=0; i<8; i = i+1) begin: my_block_name
            assign out[i] = in[8-i-1];
        end
    endgenerate
endmodule


Replication operator⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector4

這題將8bit轉成32bit,並且多餘的24bit要填入in[7],所以語法如下。

Verilog
module top_module (
    input [7:0] in,
    output [31:0] out );//

    assign out = { { 24{ in[7] } },in};

endmodule


More replication⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector5

這題也是練習replication,aaaaabbbbbcccccdddddeeeee可以寫成{ {5{a}},{5{b}},{5{c}},{5{d}},{5{e}}},abcdeabcdeabcdeabcdeabcde可以寫成{5{a,b,c,d,e}}

Verilog
module top_module (
    input a, b, c, d, e,
    output [24:0] out );//
    assign out = ~({ { 5{a} },{5{b}},{5{c}},{5{d}},{5{e}}} ^ {5{a,b,c,d,e}});
endmodule


Modules: Hierarchy⚓︎

Modules⚓︎

Website: https://hdlbits.01xz.net/wiki/Module

這題在教如何引用module。

Verilog
module top_module ( input a, input b, output out );
    mod_a moda(.out(out),.in1(a),.in2(b));
endmodule


Connecting ports by position⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_pos

這題跟上題差不多,題目要求我們照著argument的位置接線。

Verilog
module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    module mod_a ( out1, out2, a, b, c, d );
endmodule


Connecting ports by name⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_name

這題跟上題差不多,只是上題是要求根據argument的位置接線,這題是要求跟據argument的名字接線。

Verilog
module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a moda(.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d));
endmodule


Three modules⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_shift

這題是練習用接線的方式,將3個dff串接在一起。

Verilog
module top_module ( input clk, input d, output q );
    wire q1,q2;
    my_dff dff1( .clk(clk), .d(d), .q(q1));
    my_dff dff2( .clk(clk), .d(q1), .q(q2));
    my_dff dff3( .clk(clk), .d(q2), .q(q));
endmodule


Modules and vectors⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_shift8

這題跟上題差不多,只是後面多接了一個multiplexer。而multiplexer可以用always block實現,速度會比用if else還快,而因為multiplexer是combinational logic,所以要用blocking assignments。

Verilog
module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);
    wire [7:0]q1,q2,q3;
    my_dff8 dff1( .clk(clk), .d(d), .q(q1));
    my_dff8 dff2( .clk(clk), .d(q1), .q(q2));
    my_dff8 dff3( .clk(clk), .d(q2), .q(q3));
    always @(*)
        case(sel)
            2'b00: q = d;
            2'b01: q = q1;
            2'b10: q = q2;
            2'b11: q = q3;
        endcase
endmodule


Adder 1⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_add

這題單純把兩個16bit adder接在一起,值得注意的是,如果argument不想接線,直接留空就行了。

Verilog
module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire c1;
    add16 add_1( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(c1));
    add16 add_2( .a(a[31:16]), .b(b[31:16]), .cin(c1), .sum(sum[31:16]), .cout());
endmodule


Adder 2⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_fadd

這題跟上題差不多,只是要多寫一個1 bit full adder,可以用concatenation來實現。

Verilog
module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
    wire c1;
    add16 add_1( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(c1));
    add16 add_2( .a(a[31:16]), .b(b[31:16]), .cin(c1), .sum(sum[31:16]), .cout());
endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );
    assign {cout, sum} = a + b + cin;
endmodule


Carry-select adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_cseladd

這題要我們接線CSA(carry-select adder),CSA的好處在於已經偷算完cin是0和1的case,等到低位元進位後,就能馬上用multiplexer輸出算好的結果,缺點就是因為同時要算cin是0和1的結果,面積會變兩倍。

Verilog
module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);  
    wire sel;
    wire [15:0] s1,s2;
    add16 add1( .a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum[15:0]), .cout(sel));
    add16 add2( .a(a[31:16]), .b(b[31:16]), .cin(1'b0), .sum(s1), .cout());
    add16 add3( .a(a[31:16]), .b(b[31:16]), .cin(1'b1), .sum(s2), .cout());
    always @(*)
        case(sel)
            1'b0: sum[31:16] = s1;
            1'b1: sum[31:16] = s2;
        endcase
endmodule


Adder-subtractor⚓︎

Website: https://hdlbits.01xz.net/wiki/Module_addsub

這題在教如何快速實現減法,也就是a - b = a + ~(b) + 1這件事。

Verilog
module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire c1;
    wire [31:0] b_xor;
    assign b_xor = b ^ {32{sub}};
    add16 add_1( .a(a[15:0]), .b(b_xor[15:0]), .cin(sub), .sum(sum[15:0]), .cout(c1));
    add16 add_2( .a(a[31:16]), .b(b_xor[31:16]), .cin(c1), .sum(sum[31:16]), .cout());
endmodule


Procedures⚓︎

Always blocks (combinational)⚓︎

Website: https://hdlbits.01xz.net/wiki/Alwaysblock1

這題在講說combinational logic可以有assign和always @(*)兩種寫法。然後有個細節要注意,assign的左值要用wire,always的左值要用reg,雖然這兩者在合成電路後沒差。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module(
    input a, 
    input b,
    output wire out_assign,
    output reg out_alwaysblock
);
    assign out_assign = a & b;
    always @(*)
        out_alwaysblock = a & b;
endmodule


Always blocks (clocked)⚓︎

Website: https://hdlbits.01xz.net/wiki/Alwaysblock2

這題就是在講combinational logic和sequential logic的差別。如果是clock always的話,最好賦值使用non-blocking。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module(
    input clk,
    input a,
    input b,
    output wire out_assign,
    output reg out_always_comb,
    output reg out_always_ff   );
    assign out_assign = a ^ b;
    always@(*)
        out_always_comb = a ^ b;
    always@(posedge clk)
        out_always_ff <= a ^ b;
endmodule


If statement⚓︎

Website: https://hdlbits.01xz.net/wiki/Always_if

這題分別要求要寫三元運算和在combinational block中寫if/else,可能要注意的是cond可以共用。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module(
    input a,
    input b,
    input sel_b1,
    input sel_b2,
    output wire out_assign,
    output reg out_always   ); 
    wire cond;
    assign cond = sel_b1 & sel_b2;
    assign out_assign = cond ? b : a;
    always@(*)begin
        if(cond)begin
            out_always = b;
        end
        else begin
            out_always = a;
        end
    end 
endmodule


If statement latches⚓︎

Website: https://hdlbits.01xz.net/wiki/Always_if2

這題在講說要寫清楚else和default,不然verilog會合成出latch。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  ); //

    always @(*) begin
        if (cpu_overheated)
           shut_off_computer = 1;
        else
           shut_off_computer = 0;
    end

    always @(*) begin
        if (~arrived)
           keep_driving = ~gas_tank_empty;
        else
           keep_driving = 1'b0;
    end

endmodule


Case statement⚓︎

Website: https://hdlbits.01xz.net/wiki/Always_case

這題在教case如何使用,然後要記得寫default防止latch。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module ( 
    input [2:0] sel, 
    input [3:0] data0,
    input [3:0] data1,
    input [3:0] data2,
    input [3:0] data3,
    input [3:0] data4,
    input [3:0] data5,
    output reg [3:0] out   );//

    always@(*) begin  // This is a combinational circuit
        case(sel)
            3'b000: out = data0;
            3'b001: out = data1;
            3'b010: out = data2;
            3'b011: out = data3;
            3'b100: out = data4;
            3'b101: out = data5;
            default: out = 4'b0000;
        endcase
    end

endmodule


Priority encoder⚓︎

Website: https://hdlbits.01xz.net/wiki/Always_case2

這題要寫一個encoder,我看了卡諾圖後,發現用if else或卡諾圖畫的沒什麼太大的差異,卡諾圖的gate level少了一點,但是gate多了一些,所以這題練習用if else寫。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always@(*)begin
        if(in[0]) pos = 2'b00;
        else if(in[1]) pos = 2'b01;
        else if(in[2]) pos = 2'b10;
        else if(in[3]) pos = 2'b11;
        else pos= 2'b00;
    end
endmodule


Priority encoder with casez⚓︎

Website: https://hdlbits.01xz.net/wiki/Always_casez

這題跟上題差不多,只是嘗試用casez實作encoder。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos );
    always@(*)begin
        casez(in)
            8'bzzzzzzz1: pos = 3'b000;
            8'bzzzzzz10: pos = 3'b001;
            8'bzzzzz100: pos = 3'b010;
            8'bzzzz1000: pos = 3'b011;
            8'bzzz10000: pos = 3'b100;
            8'bzz100000: pos = 3'b101;
            8'bz1000000: pos = 3'b110;
            8'b10000000: pos = 3'b111;
            default:     pos = 3'b000;
        endcase
    end
endmodule


Avoiding latches⚓︎

Website: https://hdlbits.01xz.net/wiki/Always_nolatches

這題在練習如何在有大量output情形時,透過預先寫默認的輸入來減少行數,而這種寫法對於合成電路沒什麼影響,因為實際的電路不是照著程式碼一行一行執行。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 
    always@(*)begin
        up = 1'b0;
        down = 1'b0;
        left = 1'b0;
        right =1'b0;
        case(scancode)
            16'he06b: left= 1'b1;
            16'he072: down= 1'b1;
            16'he074: right= 1'b1;
            16'he075: up= 1'b1;
        endcase
    end
endmodule


More Verilog Features⚓︎

Conditional ternary operator⚓︎

Website: https://hdlbits.01xz.net/wiki/Conditional

這題在教三元運算的使用。題目說要做一個4-to-1 MUX,可以簡單用3個2元運算接出電路。

Verilog
module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//

    // assign intermediate_result1 = compare? true: false;
    wire [7:0]w1,w2;
    assign w1 = (a<b)? a : b;
    assign w2 = (c<d)? c : d;
    assign min = (w1<w2)? w1 : w2;
endmodule


Reduction operators⚓︎

Website: https://hdlbits.01xz.net/wiki/Reduction

這題練習reduction operator,透過assign parity =^in,省去了冗長的in運算。

Verilog
module top_module (
    input [7:0] in,
    output parity); 
    assign parity = ^in;
endmodule


Reduction: Even wider gates⚓︎

Website: https://hdlbits.01xz.net/wiki/Gates100

這題跟上題差不多,只是位數變多了。

Verilog
module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    assign out_and = &in;
    assign out_or = |in;
    assign out_xor = ^in;
endmodule


Combinational for-loop: Vector reversal 2⚓︎

Website: https://hdlbits.01xz.net/wiki/Vector100r

這題教程推薦用always block來實作reversal,就可以不用寫generate了。

Verilog
module top_module( 
    input [99:0] in,
    output [99:0] out
);
    integer i;
    always@(*)begin
        for(i=0;i<100;i++)begin
            out[i] = in[99-i];
        end
    end
endmodule


Combinational for-loop: 255-bit population count⚓︎

Website: https://hdlbits.01xz.net/wiki/Popcount255

這題要算陣列中元素的數量,可以用for loop來實現,然後記得out要初始化為0。

Verilog
module top_module( 
    input [254:0] in,
    output [7:0] out );
    integer i;
    always@(*)begin
        out = 8'b00000000;
        for(i=0;i<255;i++)begin
            out = out + in[i];
        end
    end
endmodule


Generate for-loop: 100-bit binary adder 2⚓︎

Website: https://hdlbits.01xz.net/wiki/Adder100i

這題在練習100bit的加法,因為題目要求用module實作1bit full adder,所以這裡只能用generate初始化。

Verilog
module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );

    full_adder fa_first(.a(a[0]),.b(b[0]),.cin(cin),.cout(cout[0]),.sum(sum[0]));

    genvar i;
    generate
        for(i=1;i<100;i++)begin: block_name
            full_adder fa(.a(a[i]),.b(b[i]),.cin(cout[i-1]),.cout(cout[i]),.sum(sum[i]));
        end
    endgenerate
endmodule

module full_adder(input a,input b,input cin,output cout,output sum);
    assign {cout,sum} = a + b + cin;
endmodule


Generate for-loop: 100-digit BCD adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Bcdadd100

這題跟上題差不多,只是將adder變成了BCD-adder。

Verilog
module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );

    wire [99:0]w;
    assign cout = w[99];
    bcd_fadd bcd_fadd_first(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(w[0]),.sum(sum[3:0]));

    genvar i;
    generate
        for(i=1;i<100;i++)begin:block_bcd
            bcd_fadd bf(.a(a[4*i+3:4*i]),.b(b[4*i+3:4*i]),.cin(w[i-1]),.cout(w[i]),.sum(sum[4*i+3:4*i]));
        end
    endgenerate
endmodule


Circuits⚓︎

Combinational Logic⚓︎

Basic Gates⚓︎

Wire⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4h

這題就單純接線。

Verilog
module top_module (
    input in,
    output out);
    assign out = in;
endmodule


GND⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4i

這題就單純接線。

Verilog
module top_module (
    output out);
    assign out = 1'b0;
endmodule


NOR⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4e

這題就單純接線。

Verilog
module top_module (
    input in1,
    input in2,
    output out);
    assign out = ~ (in1 | in2);
endmodule


Another gate⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4f

這題就單純接線。

Verilog
module top_module (
    input in1,
    input in2,
    output out);
    assign out = in1 & (~in2);
endmodule


Two gates⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4g

這題就單純接線。

Verilog
module top_module (
    input in1,
    input in2,
    input in3,
    output out);
    assign out = (~(in1 ^ in2))^ in3;
endmodule


More logic gates⚓︎

Website: https://hdlbits.01xz.net/wiki/Gates

這題考各種gate的運算。

Verilog
module top_module( 
    input a, b,
    output out_and,
    output out_or,
    output out_xor,
    output out_nand,
    output out_nor,
    output out_xnor,
    output out_anotb
);
    assign out_and   = a & b;
    assign out_or    = a | b;
    assign out_xor   = a ^ b;
    assign out_nand  = ~(a & b);
    assign out_nor   = ~(a | b);
    assign out_xnor  = ~(a ^ b);
    assign out_anotb = a & (~b);
endmodule


7420 chip⚓︎

Website: https://hdlbits.01xz.net/wiki/7420

這題考稍微複雜的接線。

Verilog
module top_module ( 
    input p1a, p1b, p1c, p1d,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
    assign p1y = ~(p1a & p1b & p1c & p1d);
    assign p2y = ~(p2a & p2b & p2c & p2d);
endmodule


Truth tables⚓︎

Website: https://hdlbits.01xz.net/wiki/Truthtable1

這題給了真值表,可以進一步使用卡諾圖化簡。

Verilog
module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output f   // one output
);
    assign f = (x3 & x1) | ((~x3) & x2);
endmodule


Two-bit equality⚓︎

Website: https://hdlbits.01xz.net/wiki/Mt2015_eq2

這題用三元運算子就能解決。

Verilog
module top_module ( input [1:0] A, input [1:0] B, output z ); 
    assign z = (A == B)? 1'b1: 1'b0;
endmodule


Simple circuit A⚓︎

Website: https://hdlbits.01xz.net/wiki/Mt2015_q4a

這題照題目assign就行,如果從類比層面來看,not gate會比and,or,xor還小,強烈推薦多化簡成not gate。

Verilog
module top_module (input x, input y, output z);
    assign  z = x & (~y);
endmodule


Simple circuit B⚓︎

Website: https://hdlbits.01xz.net/wiki/Mt2015_q4b

這題透過觀察波形,寫出組合邏輯。

Verilog
module top_module ( input x, input y, output z );
    assign z = ~(x ^ y);
endmodule


Combine circuits A and B⚓︎

Website: https://hdlbits.01xz.net/wiki/Mt2015_q4

這題只是將上兩題當作當作submodule後接線。

Verilog
module top_module (input x, input y, output z);
    wire wa1,wa2,wb1,wb2;
    A IA1(.x(x), .y(y), .z(wa1));
    A IA2(.x(x), .y(y), .z(wa2));
    B IB1(.x(x), .y(y), .z(wb1));
    B IB2(.x(x), .y(y), .z(wb2));
    assign z = ( wa1 | wb1 ) ^ ( wa2  & wb2 );
endmodule

module A (input x, input y, output z);
    assign  z = x & (~y);
endmodule

module B ( input x, input y, output z );
    assign z = ~(x ^ y);
endmodule


Ring or vibrate?⚓︎

Website: https://hdlbits.01xz.net/wiki/Ringer

這題題目要求用gate寫出符合敘述的邏輯。

Verilog
module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);
    assign motor = ring & vibrate_mode;
    assign ringer = ring & (~vibrate_mode);
endmodule


Thermostat⚓︎

Website: https://hdlbits.01xz.net/wiki/Thermostat

這題跟上題差不多,就是照著條件接出對應的電路。

Verilog
module top_module (
    input too_cold,
    input too_hot,
    input mode,
    input fan_on,
    output heater,
    output aircon,
    output fan
); 
    assign heater = mode & too_cold;
    assign aircon = (~mode) & too_hot;
    assign fan = heater | aircon | fan_on;
endmodule


3-bit population count⚓︎

Website: https://hdlbits.01xz.net/wiki/Popcount3

這題就是寫個全加器。

Verilog
module top_module( 
    input [2:0] in,
    output [1:0] out );
    assign out = in[2] + in[1] + in[0];
endmodule


Gates and vectors⚓︎

Website: https://hdlbits.01xz.net/wiki/Gatesv

這題就是練習assign一排運算。

Verilog
module top_module( 
    input [3:0] in,
    output [2:0] out_both,
    output [3:1] out_any,
    output [3:0] out_different );
    assign out_both = in[2:0] & in[3:1];
    assign out_any = in[2:0] | in[3:1];
    assign out_different = in [3:0] ^ {in[0],in[3:1]};
endmodule


Even longer vectors⚓︎

Website: https://hdlbits.01xz.net/wiki/Gatesv100

這題跟上題差不多,只是input vector變長了。

Verilog
module top_module( 
    input [99:0] in,
    output [98:0] out_both,
    output [99:1] out_any,
    output [99:0] out_different );
    assign out_both = in[98:0] & in[99:1];
    assign out_any = in[98:0] | in[99:1];
    assign out_different = in [99:0] ^ {in[0],in[99:1]};
endmodule


Multiplexers⚓︎

2-to-1 multiplexer⚓︎

Website: https://hdlbits.01xz.net/wiki/Mux2to1

用三元運算子就能輕鬆寫出multiplexer。

Verilog
module top_module( 
    input a, b, sel,
    output out ); 
    assign out = sel? b: a;
endmodule


2-to-1 bus multiplexer⚓︎

Website: https://hdlbits.01xz.net/wiki/Mux2to1v

跟上題差不多,用三元運算子就能輕鬆寫出vector的multiplexer。

Verilog
module top_module( 
    input [99:0] a, b,
    input sel,
    output [99:0] out );
    assign out = sel ? b : a;
endmodule


9-to-1 multiplexer⚓︎

Website: https://hdlbits.01xz.net/wiki/Mux9to1v

這題可以用case來實現9-to-1 multiplexer。

Verilog
module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output [15:0] out );
    always@(*)begin
        case(sel)
            4'b0000: out = a;
            4'b0001: out = b;
            4'b0010: out = c;
            4'b0011: out = d;
            4'b0100: out = e;
            4'b0101: out = f;
            4'b0110: out = g;
            4'b0111: out = h;
            4'b1000: out = i;
            default: out = {16{1'b1}};
        endcase
    end
endmodule


256-to-1 multiplexer⚓︎

Website: https://hdlbits.01xz.net/wiki/Mux256to1

這題講述sel也可以放在index的位置。

Verilog
module top_module( 
    input [255:0] in,
    input [7:0] sel,
    output out );
    assign out = in[sel];
endmodule


256-to-1 4-bit multiplexer⚓︎

Website: https://hdlbits.01xz.net/wiki/Mux256to1v

題目講說assign out = in[4*sel+3 :4*sel];會編不過,所以可以改寫成assign out = in[4*sel +:4];,從4*sel的地方往上取4位。

Verilog
module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    assign out = in[4*sel +:4];
endmodule


Arithmetic Circuits⚓︎

Half adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Hadd

這題就是寫一個半加器。

Verilog
module top_module( 
    input a, b,
    output cout, sum );
    assign cout = a & b;
    assign sum = a ^ b;
endmodule


Full adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Fadd

這題就是寫一個全加器。

Verilog
module top_module( 
    input a, b, cin,
    output cout, sum );
    assign {cout,sum} = a + b + cin;
endmodule


3-bit binary adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Adder3

這題就是將3個全加器串在一起。

Verilog
module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );
    FA FA1(.a(a[0]),.b(b[0]),.cin(cin),.cout(cout[0]),.sum(sum[0]));
    FA FA2(.a(a[1]),.b(b[1]),.cin(cout[0]),.cout(cout[1]),.sum(sum[1]));
    FA FA3(.a(a[2]),.b(b[2]),.cin(cout[1]),.cout(cout[2]),.sum(sum[2]));
endmodule

module FA( 
    input a, b, cin,
    output cout, sum );
    assign {cout,sum} = a + b + cin;
endmodule


Adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4j

這題就是將4個全加器串在一起,順便練習用generate block寫了for loop。

Verilog
module top_module (
    input [3:0] x,
    input [3:0] y, 
    output [4:0] sum);
    wire [4:1]cout;
    assign sum[4] = cout[4];
    FA FAA(.a(x[0]),.b(y[0]),.cin(1'b0),.cout(cout[1]),.sum(sum[0]));
    genvar i;
    generate
        for(i=1;i<4;i++)begin:block
            FA FAA(.a(x[i]),.b(y[i]),.cin(cout[i]),.cout(cout[i+1]),.sum(sum[i]));
        end
    endgenerate
endmodule

module FA( 
    input a, b, cin,
    output cout, sum );
    assign {cout,sum} = a + b + cin;
endmodule


Signed addition overflow⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q1c

這題單純練習overflow的判別,也就是兩正數相加或兩負數相減時,分別得到負數和正數,那就是發生overflow。

Verilog
module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
);
    assign s = a + b;
    assign overflow = (a[7]&b[7]&(~s[7])) | ((~a[7])&(~b[7])&s[7]);
endmodule


100-bit binary adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Adder100

這題在練習如何用behavioural code描述電路。

Verilog
module top_module( 
    input [99:0] a, b,
    input cin,
    output cout,
    output [99:0] sum );
    assign {cout,sum} = a + b + cin;
endmodule


4-digit BCD adder⚓︎

Website: https://hdlbits.01xz.net/wiki/Bcdadd4

這題在練習串接BCD adder。

Verilog
module top_module ( 
    input [15:0] a, b,
    input cin,
    output cout,
    output [15:0] sum );
    wire [3:0] co;
    bcd_fadd bf1(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(co[0]),.sum(sum[3:0]));
    bcd_fadd bf2(.a(a[7:4]),.b(b[7:4]),.cin(co[0]),.cout(co[1]),.sum(sum[7:4]));
    bcd_fadd bf3(.a(a[11:8]),.b(b[11:8]),.cin(co[1]),.cout(co[2]),.sum(sum[11:8]));
    bcd_fadd bf4(.a(a[15:12]),.b(b[15:12]),.cin(co[2]),.cout(co[3]),.sum(sum[15:12]));
    assign cout = co[3];
endmodule


Karnaugh Map to Circuit⚓︎

3-variable⚓︎

Website: https://hdlbits.01xz.net/wiki/Kmap1

這題練習如何化簡k-map。

Verilog
module top_module(
    input a,
    input b,
    input c,
    output out  ); 
    assign out = a | b | c;
endmodule


4-variable(1)⚓︎

Website: https://hdlbits.01xz.net/wiki/Kmap2

這題練習如何化簡k-map,值得注意的是,k map畫圈要重疊,才不會發生hazard。

Verilog
module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out = (~a & ~d) | (~b & ~c) | (a & ~b & d) | (a & c & d) | (b & c & d);
endmodule


4-variable(2)⚓︎

Website: https://hdlbits.01xz.net/wiki/Kmap3

這題練習如何化簡k-map,don't care的部分可以既看成0或看成1化簡,就看方便化簡。

Verilog
module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out = a | (~b & c);
endmodule


4-variable(3)⚓︎

Website: https://hdlbits.01xz.net/wiki/Kmap4

這題練習如何化簡k-map,有點腦筋急轉彎,這題反而不能想用sum of product或product of sum。

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⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q2

這題練習如何畫k map並化簡。

Verilog
module top_module (
    input a,
    input b,
    input c,
    input d,
    output out_sop,
    output out_pos
);
//K map
//cd\ab 00 01 11 10
//   00  0  0  d  d  
//   01  0  0  0  0
//   11  d  1  1  d
//   10  1  0  0  0
    assign out_sop = (c & d) | (~a & ~b & c);
    assign out_pos = c & (~a | b) & (~b | d);
endmodule


Karnaugh map(1)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q3

這題練習如何畫k map並化簡。

Verilog
module top_module (
    input [4:1] x, 
    output f );
    assign f = (~x[1] & x[3]) | (x[2] & x[4]);
endmodule


Karnaugh map(2)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2012_q1g

這題練習如何畫k map並化簡。

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⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q3

這題練習如何畫k map並化簡,比較有意思的是,這題用到了multiplexer畫k-map。

Verilog
module top_module (
    input c,
    input d,
    output [3:0] mux_in
); 
    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 Flip-Flops⚓︎

D flip-flop⚓︎

Website: https://hdlbits.01xz.net/wiki/Dff

這題單純練習如何用sequential block建立DFF,注意要用non-blocking assignment。

Verilog
module top_module (
    input clk,    // Clocks are used in sequential circuits
    input d,
    output reg q );//

    // Use a clocked always block
    //   copy d to q at every positive edge of clk
    //   Clocked always blocks should use non-blocking assignments
    always@(posedge clk)
        q <= d;
endmodule


D flip-flops⚓︎

Website: https://hdlbits.01xz.net/wiki/Dff8

這題單純練習如何用sequential block建立8-bit input DFF。

Verilog
module top_module (
    input clk,
    input [7:0] d,
    output reg [7:0] q
);
    always@(posedge clk)
        q <= d;
endmodule


DFF with reset⚓︎

Website: https://hdlbits.01xz.net/wiki/Dff8r

這題單純練習如何用sequential block建立8-bit input with DFF synchronous reset。

Verilog
module top_module (
    input clk,
    input reset,            // Synchronous reset
    input [7:0] d,
    output reg [7:0] q
);
    always@(posedge clk)begin
        if(reset) q <= 8'b0000_0000;
        else q <= d;
    end
endmodule


DFF with reset value⚓︎

Website: https://hdlbits.01xz.net/wiki/Dff8p

這題練習負緣更新,然後題目所說在reset時要更新成0x34,0x的意思是16進位制。

Verilog
module top_module (
    input clk,
    input reset,
    input [7:0] d,
    output reg [7:0] q
);
    always@(negedge clk)begin
        if(reset) q <= 8'h34;
        else q <= d;
    end
endmodule


DFF with asynchronous reset⚓︎

Website: https://hdlbits.01xz.net/wiki/Dff8ar

這題要做異步復位的DFF。

Verilog
module top_module (
    input clk,
    input areset,   // active high asynchronous reset
    input [7:0] d,
    output reg [7:0] q
);
    always@(posedge clk, posedge areset)begin
        if(areset) q <= 8'b0000_0000;
        else q <= d;
    end
endmodule


DFF with byte enable⚓︎

Website: https://hdlbits.01xz.net/wiki/Dff16e

這題就是DFF加上enable。

Verilog
module top_module (
    input clk,
    input resetn,
    input [1:0] byteena,
    input [15:0] d,
    output reg[15:0] q
);
    always@(posedge clk)begin
        if(~resetn) q <= 16'h0000;
        else begin
            q[15:8] <= byteena[1] ? d[15:8]: q[15:8];
            q[7:0] <= byteena[0] ? d[7:0]: q[7:0];
        end
    end
endmodule


D Latch⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4a

這題練習寫d latch,因為d latch是level-sensitive,所以要用always@(*),而因為是sequential logic,所以要用non-blocking assignment。

Verilog
module top_module (
    input d, 
    input ena,
    output reg q);
    always@(*)begin
        if(ena) q <= d;
    end
endmodule


DFF(1)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4b

這題練習寫DFF with asynchronous reset。

Verilog
module top_module (
    input clk,
    input d, 
    input ar,   // asynchronous reset
    output reg q);
    always@(posedge clk,posedge ar)begin
        if(ar) q <= 1'b0;
        else q <= d;
    end
endmodule


DFF(2)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4c

這題練習寫DFF with synchronous reset,跟上題不同的是,不用考慮reset的正緣觸發。

Verilog
module top_module (
    input clk,
    input d, 
    input r,   // synchronous reset
    output reg q);
    always@(posedge clk)begin
        if(r) q <= 1'b0;
        else q <= d;
    end
endmodule


DFF+gate⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4d

這題練習寫DFF加上gate的填寫。

Verilog
module top_module (
    input clk,
    input in, 
    output reg out);
    always@(posedge clk)begin
        out <= out ^ in;
    end
endmodule


Mux and DFF(1)⚓︎

Website: https://hdlbits.01xz.net/wiki/Mt2015_muxdff

這題練習一個DFF加上一個mux。

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(2)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2014_q4a

這題練習一個DFF加上超過1個gate,此時就可以考慮將combinational logic另外在sequential block外assign好。

Verilog
module top_module (
    input clk,
    input w, R, E, L,
    output reg Q
);  
    wire q_in;
    assign q_in = L ? R : (E ? w : Q);
    always@(posedge clk)begin
        Q <= q_in;
    end
endmodule


DFFs and gates⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q4

這題只是寫3個DFF。

Verilog
module top_module (
    input clk,
    input x,
    output z
); 
    reg q1,q2,q3;
    assign z = ~(q1 | q2 | q3);
    always@(posedge clk)begin
        q1 <= q1 ^ x;
        q2 <= ~q2 & x;
        q3 <= ~q3 | x;
    end
endmodule


Create circuit from truth table⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q7

這題練習寫JK-FF。

Verilog
module top_module (
    input clk,
    input j,
    input k,
    output reg Q); 
    always @(posedge clk)begin
        case({j,k})
            2'b00: Q <= Q;
            2'b01: Q <= 1'b0;
            2'b10: Q <= 1'b1;
            2'b11: Q <= ~Q;
        endcase
    end
endmodule


Detect an edge⚓︎

Website: https://hdlbits.01xz.net/wiki/Edgedetect

這題練習寫edge detection,為了比較上個clk的輸入,要多開一個dff存。

Verilog
module top_module (
    input clk,
    input [7:0] in,
    output reg [7:0] pedge
);
    reg [7:0] in_prev;
    always@(posedge clk)begin
        in_prev <= in;
        pedge <= ~in_prev & in;
    end
endmodule


Detect both edges⚓︎

Website: https://hdlbits.01xz.net/wiki/Edgedetect2

這題練習寫edge detection,跟上題不同的是,要同時判斷0變1和1變0。

Verilog
module top_module (
    input clk,
    input [7:0] in,
    output reg [7:0] anyedge
);
    reg [7:0] in_prev;
    always@(posedge clk)begin
        in_prev <= in;
        anyedge <= in ^ in_prev;
    end
endmodule


Edge capture register⚓︎

Website: https://hdlbits.01xz.net/wiki/Edgecapture

這題最難的地方就是將edge detection變成edge capture,最簡單的做法就是多or上回合的output。

Verilog
module top_module (
    input clk,
    input reset,
    input [31:0] in,
    output reg [31:0] out
);
    reg [31:0] in_prev;
    always@(posedge clk)begin
        in_prev <= in;
        if(reset)
            out <= 32'h0000_0000;
        else begin
            out <= ~in & in_prev | out;
        end
    end
endmodule


Dual-edge triggered flip-flop⚓︎

Website: https://hdlbits.01xz.net/wiki/Dualedge

這題我直接查解答,這個電路設計也太酷。

Verilog
module top_module (
    input clk,
    input d,
    output q
);
    // Why does this work? 
    // After posedge clk, p changes to d^n. Thus q = (p^n) = (d^n^n) = d.
    // After negedge clk, n changes to p^n. Thus q = (p^n) = (p^d^p) = d.
    reg r1, r2;
    assign q = r1 ^ r2;
    always@(posedge clk) r1 <= r2 ^ d;
    always@(negedge clk) r2 <= r1 ^ d;
endmodule


Counters⚓︎

Four-bit binary counter⚓︎

Website: https://hdlbits.01xz.net/wiki/Count15

這題就是用always來計數。

Verilog
module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output reg[3:0] q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0000;
        else q<= q + 4'b0001;
    end
endmodule


Decade counter⚓︎

Website: https://hdlbits.01xz.net/wiki/Count10

這題就是用always來計數,只是數到9,多一個條件。

Verilog
module top_module (
    input clk,
    input reset,        // Synchronous active-high reset
    output reg[3:0] q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0000;
        else if(q == 4'b1001) q <= 4'b0000;
        else q<= q + 4'b0001;
    end
endmodule


Decade counter again⚓︎

Website: https://hdlbits.01xz.net/wiki/Count1to10

這題就是用always來計數,只是變成從1數到10。

Verilog
module top_module (
    input clk,
    input reset,
    output reg[3:0] q);
    always@(posedge clk)begin
        if(reset) q <=4'b0001;
        else if(q == 4'b1010) q<=4'b0001;
        else q <= q + 4'b0001;
    end
endmodule


Slow decade counter⚓︎

Website: https://hdlbits.01xz.net/wiki/Countslow

這題跟上題差不多,只是變成用另一個輸入計數。

Verilog
module top_module (
    input clk,
    input slowena,
    input reset,
    output reg[3:0] q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0000;
        else if(slowena)begin
            if(q == 4'b1001) q<= 4'b0000;
            else q <= q + 4'b0001;
        end
        else q <= q;
    end
endmodule


Counter 1-12⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q7a

這題給了完整的計數器,然後要求外接控制reset和數到12。

Verilog
module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); //
    assign c_enable = enable;
    assign c_load = reset | (enable & (Q == 4'b1100));
    assign c_d = 4'b0001;
    count4 the_counter (clk, c_enable, c_load, c_d ,Q);
endmodule


Counter 1000⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q7b

這題給了BCD counter,然後要連續接3個BCD counter數到1000。

Verilog
module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); //
    wire [3:0] one, ten, hundred;
    wire is_ten, is_hundred;
    assign is_ten = (one == 4'b1001);
    assign is_hundred = is_ten & (ten == 4'b1001);
    assign c_enable = {is_hundred,is_ten,1'b1};
    assign OneHertz = is_hundred & (hundred == 4'b1001);
    bcdcount counter0 (clk, reset, c_enable[0], one);
    bcdcount counter1 (clk, reset, c_enable[1], ten);
    bcdcount counter2 (clk, reset, c_enable[2], hundred);
endmodule


4-digit decimal counter⚓︎

Website: https://hdlbits.01xz.net/wiki/Countbcd

這題要自己刻一個BCD,然後要將4個BCD相接,數到9999。

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    wire is_ten , is_hundred, is_thousand;
    assign is_ten = (q[3:0] == 4'b1001);
    assign is_hundred = (q[7:4] == 4'b1001) & is_ten;
    assign is_thousand = (q[11:8] == 4'b1001) & is_hundred & is_ten;
    assign ena = {is_thousand, is_hundred, is_ten};
    BCD BCD0(.clk(clk),.reset(reset),.enable( 1'b1 ),.q(q[3:0]));
    BCD BCD1(.clk(clk),.reset(reset),.enable(ena[1]),.q(q[7:4]));
    BCD BCD2(.clk(clk),.reset(reset),.enable(ena[2]),.q(q[11:8]));
    BCD BCD3(.clk(clk),.reset(reset),.enable(ena[3]),.q(q[15:12]));
endmodule

module BCD(
    input clk,
    input reset,
    input enable,
    output reg [4:0] q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0000;
        else if(enable)begin
            if(q == 4'b1001) q <= 4'b0000;
            else q <= q + 4'b0001;
        end
        else q <= q;
    end
endmodule


12-hour clock⚓︎

Website: https://hdlbits.01xz.net/wiki/Count_clock

這題刻一個時鐘,算是目前刷題第一次要寫很多程式。

Verilog
module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss);

    wire enas2,enam1,enam2,enah1,enah2,enapm,ld;
    BCD_zero_to_nine s1( .clk(clk), .reset(reset), .enable(ena), .q(ss[3:0]));

    assign enas2 = ena & (ss[3:0] == 4'b1001);
    BCD_zero_to_six s2( .clk(clk), .reset(reset), .enable(enas2), .q(ss[7:4]));

    assign enam1 = enas2 & (ss[7:4] == 4'b0101);
    BCD_zero_to_nine m1( .clk(clk), .reset(reset), .enable(enam1), .q(mm[3:0]));

    assign enam2 = enam1 & (mm[3:0] == 4'b1001);
    BCD_zero_to_six m2( .clk(clk), .reset(reset), .enable(enam2), .q(mm[7:4]));    

    assign enah1 = enam2 & (mm[7:4] == 4'b0101);
    assign ld = enah1 & (hh == 8'b0001_0010);    
    BCD_zero_to_nine_wload h1( .clk(clk), .reset(reset), .enable(enah1), .load(ld), .q(hh[3:0]));

    assign enah2 = (enah1 & (hh[3:0] == 4'b1001)) | ld;
    BCD_zero_to_one_wload h2( .clk(clk), .reset(reset), .enable(enah2), .load(ld), .q(hh[7:4]));

    assign enapm = enah1 & (hh == 8'b0001_0001);
    PM is_pm( .clk(clk), .reset(reset), .enable(enapm), .pm(pm));
endmodule

module BCD_zero_to_nine(
    input clk,
    input reset,
    input enable,
    output reg [3:0]q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0000;
        else if(enable)begin
            if(q == 4'b1001) q <= 4'b0000;
            else q <= q + 4'b0001;
        end
        else q <= q;
    end
endmodule

module BCD_zero_to_six(
    input clk,
    input reset,
    input enable,
    output reg [3:0]q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0000;
        else if(enable)begin
            if(q == 4'b0101) q <= 4'b0000;
            else q <= q + 4'b0001;
        end
        else q <= q;
    end
endmodule

module BCD_zero_to_nine_wload(
    input clk,
    input reset,
    input enable,
    input load,
    output reg [3:0]q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0010;
        else if(enable)begin
            if(load) q <= 4'b0001;
            else if(q == 4'b1001) q <= 4'b0000;
            else q <= q + 4'b0001;
        end
        else q <= q;
    end
endmodule

module BCD_zero_to_one_wload(
    input clk,
    input reset,
    input enable,
    input load,
    output reg [3:0]q);
    always@(posedge clk)begin
        if(reset) q <= 4'b0001;
        else if(enable)begin
            if(load) q <= 4'b0000;
            else q <= q + 4'b0001;
        end
        else q <= q;
    end
endmodule

module PM(
    input clk,
    input reset,
    input enable,
    output reg pm);
    always@(posedge clk)begin
        if(reset) pm <= 1'b0;
        else if(enable) pm <= pm ^ 1'b1;
        else pm <= pm;
    end
endmodule


Shift Registers⚓︎

4-bit shift register⚓︎

Website: https://hdlbits.01xz.net/wiki/Shift4

這題就是寫個shift register,唯一要注意的是load優先級比enable大。

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, posedge areset)begin
        if(areset) q <= 4'b0000;
        else if(load) q <= data;
        else if(ena) q <= q >> 1;
        else q <= q;
    end
endmodule


Left/right rotator⚓︎

Website: https://hdlbits.01xz.net/wiki/Rotate100

這題就是寫個rotator,可以使用concatenation來實現rotate。

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) q <= data;
        else begin
            case(ena)
                2'b00: q <= q;
                2'b01: q <= { q[0], q[99:1]};
                2'b10: q <= { q[98:0], q[99]};
                2'b11: q <= q;
            endcase
        end
    end
endmodule


Left/right arithmetic shift by 1 or 8⚓︎

Website: https://hdlbits.01xz.net/wiki/Shift18

這題實作arithmetic shift,需注意的是arithmetic shift往右位移時,高位要用補數補位。

Verilog
module top_module(
    input clk,
    input load,
    input ena,
    input [1:0] amount,
    input [63:0] data,
    output reg [63:0] q); 
    always@(posedge clk)begin
        if(load) q <= data;
        else if(ena)begin
            case(amount)
                2'b00: q <= {q[62:0], 1'b0};
                2'b01: q <= {q[55:0],8'b0000_0000};
                2'b10: q <= {q[63],q[63:1]};
                2'b11: q <= {{8{q[63]}},q[63:8]};
            endcase
        end
        else q <= q;
    end
endmodule


5-bit LFSR⚓︎

Website: https://hdlbits.01xz.net/wiki/Lfsr5

這題實作LFSR。

Verilog
module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 5'h1
    output reg [4:0] q
); 
    always@(posedge clk)begin
        if(reset) q <= 5'b00001;
        else q <= {q[0],q[4],q[3] ^ q[0],q[2:1]};
    end
endmodule


3-bit LFSR⚓︎

Website: https://hdlbits.01xz.net/wiki/Mt2015_lfsr

這題跟上題一樣實作LFSR。

Verilog
module top_module (
    input [2:0] SW,      // R
    input [1:0] KEY,     // L and clk
    output [2:0] LEDR);  // Q

    always@(posedge KEY[0])begin
        LEDR <= KEY[1] ? SW: {LEDR[1]^LEDR[2],LEDR[0],LEDR[2]};
    end
endmodule


32-bit LFSR⚓︎

Website: https://hdlbits.01xz.net/wiki/Lfsr32

這題還是實作LFSR,taps的意思是指在對應的output放上xor q[0],像說taps at 1意思就是q[1] ^ q[0]

Verilog
module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 32'h1
    output reg [31:0] q
); 
    always@(posedge clk)begin
        if(reset) q <= 32'h1;
        else q <= {q[0],q[31:23],q[22]^q[0],q[21:3],q[2]^q[0],q[1]^q[0]};
    end
endmodule


Shift register(1)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q4k

這題單純練習pipeline怎麼切,總之就是多開幾個reg。

Verilog
module top_module (
    input clk,
    input resetn,   // synchronous reset
    input in,
    output reg out);
    reg q1, q2, q3;
    always@(posedge clk)begin
        if(~resetn) {q1,q2,q3,out} <= 4'b0000;
        else {q1,q2,q3,out} <= {in,q1,q2,q3};
    end
endmodule


Shift register(2)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2014_q4b

這題單純練習寫一個module,然後接成pipeline。

Verilog
module top_module (
    input [3:0] SW,
    input [3:0] KEY,
    output [3:0] LEDR
); //
    MUXDFF ff0( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(LEDR[1]), .R(SW[0]), .q(LEDR[0]));
    MUXDFF ff1( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(LEDR[2]), .R(SW[1]), .q(LEDR[1]));
    MUXDFF ff2( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(LEDR[3]), .R(SW[2]), .q(LEDR[2]));
    MUXDFF ff3( .E(KEY[1]), .clk(KEY[0]), .L(KEY[2]), .w(KEY[3]), .R(SW[3]), .q(LEDR[3]));
endmodule

module MUXDFF (
    input E,
    input clk,
    input L,
    input w,
    input R,
    output q);
    always@(posedge clk)begin
        case({L,E})
            2'b00: q <= q;
            2'b01: q <= w;
            default: q <= R;
        endcase
    end
endmodule


3-input LUT⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q12

這題單純練習寫一個shift register和multiplexer。

Verilog
module top_module (
    input clk,
    input enable,
    input S,
    input A, B, C,
    output reg Z ); 
    reg [7:0] Q;
    always@(posedge clk)begin
        if(enable) Q <= {Q[6:0],S};
        else Q <= Q;
    end
    assign Z = Q[{A,B,C}];
endmodule


More Circuits⚓︎

Rule 90⚓︎

Website: https://hdlbits.01xz.net/wiki/Rule90

這題單純練習concatenation的使用。

Verilog
module top_module(
    input clk,
    input load,
    input [511:0] data,
    output reg [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⚓︎

Website: https://hdlbits.01xz.net/wiki/Rule110

這題單純練習concatenation的使用,跟上題不同的是,這題有點卡諾圖化簡的感覺。

Verilog
module top_module(
    input clk,
    input load,
    input [511:0] data,
    output reg [511:0] q
); 
    always@(posedge clk)begin
        if(load) q <= data;
        else q <= (q ^ {q[510:0],1'b0}) | (~{1'b0,q[511:1]} & q);
    end
endmodule


Conway's Game of Life 16x16⚓︎

Website: https://hdlbits.01xz.net/wiki/Conwaylife

這題練習使用for迴圈,還有debug的耐心。

Verilog
module top_module(
    input clk,
    input load,
    input [255:0] data,
    output reg [255:0] q );
    reg [255:0] next_q;
    reg [323:0] q_padding;
    reg [3:0] answer[255:0];
    integer i,j;

    always@(*)begin
        //update q_padding
        q_padding[17:0] = {q[240],q[255:240],q[255]};
        q_padding[323:306] = {q[0],q[15:0],q[15]};
        for(i = 1; i < 17 ; i++)begin
            q_padding[i*18 +: 18] = {q[(i-1)*16],q[(i-1)*16 +: 16],q[i*16-1]};
        end
        //calculate
        for(i=0; i<16; i++)begin
            for(j=0; j<16; j++)begin
                //center is q_padding[18*(i+1)+(j+1)]
                answer[16*i + j] = q_padding[18*i+(j  )] +
                         q_padding[18*i+(j+1)] +
                         q_padding[18*i+(j+2)] +
                         q_padding[18*(i+1)+(j  )] +
                         q_padding[18*(i+1)+(j+2)] +
                         q_padding[18*(i+2)+(j  )] +
                         q_padding[18*(i+2)+(j+1)] +
                         q_padding[18*(i+2)+(j+2)];                
                case(answer[16*i + j])
                    4'b0011: next_q[16*i+j] = 1'b1;
                    4'b0010: next_q[16*i+j] = q[16*i+j];
                    default: next_q[16*i+j] = 1'b0;
                endcase
            end
        end
    end

    always@(posedge clk)begin
        if(load) q <= data;
        else q <= next_q;
    end
endmodule


Finite State Machines⚓︎

Simple FSM 1 (asynchronous reset)⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm1

這題寫個FSM,可以進一步化簡。

Verilog
module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output out);//  

    parameter A=0, B=1; 
    reg state;

    always @(posedge clk, posedge areset) begin    // This is a sequential always block
        // State flip-flops with asynchronous reset
        if(areset) state <=  B;
        else begin
            state <= ~(state ^ in);
        end
    end

    // Output logic
    assign out = state;
endmodule


Simple FSM 1 (synchronous reset)⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm1s

這題寫個FSM,跟上一題只差在Synchronous reset,這題練習正常寫FSM。

Verilog
// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
    input clk;
    input reset;    // Synchronous reset to state B
    input in;
    output out;

    // Fill in state name declarations

    reg present_state, next_state;

    always@(*)begin
        case(present_state)
            1'b0: next_state = in? 1'b0: 1'b1;
            1'b1: next_state = in? 1'b1: 1'b0;
        endcase
    end

    always @(posedge clk) begin
        if (reset)present_state <= 1'b1;
        else present_state <= next_state;
    end
    assign out = present_state;
endmodule


Simple FSM 2 (asynchronous reset)⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm2

這題寫個FSM,跟上上一題只差在邏輯有點差異。

Verilog
module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            1'b1: next_state = k? 1'b0: 1'b1;
            1'b0: next_state = j? 1'b1: 1'b0;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset) state <= 1'b0;
        else state <= next_state;
    end

    // Output logic
    assign out = state;
endmodule


Simple FSM 2 (synchronous reset)⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm2s

這題寫個FSM,跟上一題只差在Synchronous reset,這題練習正常寫FSM。

Verilog
module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            1'b1: next_state = k? 1'b0: 1'b1;
            1'b0: next_state = j? 1'b1: 1'b0;
        endcase
    end

    always @(posedge clk) begin
        // State flip-flops with synchronous reset
        if(reset) state <= 1'b0;
        else state <= next_state;
    end

    // Output logic
    assign out = state;
endmodule


Simple state transitions 3⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm3comb

這題寫個FSM,只是不需要處理clock。

Verilog
module top_module(
    input in,
    input [1:0] state,
    output [1:0] next_state,
    output out); //

    //parameter A=0, B=1, C=2, D=3;

    // State transition logic: next_state = f(state, in)
    always@(*)begin
        case(state)
            2'b00: next_state = in? 2'b01: 2'b00;
            2'b01: next_state = in? 2'b01: 2'b10;
            2'b10: next_state = in? 2'b11: 2'b00;
            2'b11: next_state = in? 2'b01: 2'b10;
        endcase
    end

    // Output logic:  out = f(state) for a Moore state machine
    assign out = &state;
endmodule


Simple one-hot state transitions 3⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm3onehot

這題state是one-hot vector,要求transition table用assign寫,滿特別的。

Verilog
module top_module(
    input in,
    input [3:0] state,
    output [3:0] next_state,
    output out); //

    parameter A=0, B=1, C=2, D=3;

    // State transition logic: Derive an equation for each state flip-flop.
    assign next_state[A] = ~in & (state[0] | state[2]);
    assign next_state[B] = in & (state[0] | state[1] | state[3]);
    assign next_state[C] = ~in & (state[1] | state[3]);
    assign next_state[D] = in & (state[2]);

    // Output logic: 
    assign out = state[3];

endmodule


Simple FSM 3 (asynchronous reset)⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm3

這題寫FSM,照著寫就結束了。

Verilog
module top_module(
    input clk,
    input in,
    input areset,
    output out); //

    // State transition logic
    reg [1:0] state, next_state;
    always@(*)begin
        case(state)
            2'b00: next_state = in? 2'b01: 2'b00;
            2'b01: next_state = in? 2'b01: 2'b10;
            2'b10: next_state = in? 2'b11: 2'b00;
            2'b11: next_state = in? 2'b01: 2'b10;
        endcase
    end
    // State flip-flops with asynchronous reset
    always@(posedge clk, posedge areset)begin
        if(areset) state <= 2'b00;
        else state <= next_state;
    end
    // Output logic
    assign out = &state;
endmodule


Simple FSM 3 (synchronous reset)⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm3s

這題寫FSM,照著寫就結束了,跟上題相比,就是把改成synchronous reset。

Verilog
module top_module(
    input clk,
    input in,
    input reset,
    output out); //

    // State transition logic
    reg [1:0] state, next_state;
    always@(*)begin
        case(state)
            2'b00: next_state = in? 2'b01: 2'b00;
            2'b01: next_state = in? 2'b01: 2'b10;
            2'b10: next_state = in? 2'b11: 2'b00;
            2'b11: next_state = in? 2'b01: 2'b10;
        endcase
    end
    // State flip-flops with synchronous reset
    always@(posedge clk)begin
        if(reset) state <= 2'b00;
        else state <= next_state;
    end
    // Output logic
    assign out = &state;
endmodule


Design a Moore FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q4

這題考閱讀,照著題意接FSM。

Verilog
module top_module (
    input clk,
    input reset,
    input [3:1] s,
    output fr3,
    output fr2,
    output fr1,
    output dfr
); 
    reg [1:0]state, next_state;
    assign next_state = {s[2],~(s[3]^s[2])&s[1]};

    always@(posedge clk)begin
        if(reset) state <= 2'b00;
        else state <= next_state;
    end

    always@(*)begin
        case(state)
            2'b00: {fr3,fr2,fr1} = 3'b111;
            2'b01: {fr3,fr2,fr1} = 3'b011;
            2'b10: {fr3,fr2,fr1} = 3'b001;
            2'b11: {fr3,fr2,fr1} = 3'b000;
        endcase
    end

    always@(posedge clk)begin
        if(reset) dfr <= 1'b1;
        else begin
            if(state > next_state) dfr <= 1'b1;
            else if(state== next_state) dfr <= dfr;
            else dfr <= 1'b0;
        end
    end
endmodule


Lemmings 1⚓︎

Website: https://hdlbits.01xz.net/wiki/Lemmings1

這題透過FSM實作遊戲的原理。

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=1, RIGHT=0, ...
    reg state, next_state;

    always @(*) begin
        // State transition logic
        case(state)
            1'b0: next_state = bump_right? 1'b1: 1'b0;
            1'b1: next_state = bump_left?  1'b0: 1'b1;
        endcase
    end

    always @(posedge clk, posedge areset) begin
        // State flip-flops with asynchronous reset
        if(areset) state <= 1'b1;
        else state <= next_state;
    end

    // Output logic
    assign walk_left = state;
    assign walk_right = ~state;
endmodule


Lemmings 2⚓︎

Website: https://hdlbits.01xz.net/wiki/Lemmings2

這題是上題的延伸,主要是bump的條件要多寫。

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 ); 
    //0 right_fall, 1 left_fall, 2 right, 3 left
    reg [1:0]state,next_state;

    always@(*)begin
        if(~ground) next_state = {1'b0,state[0]};
        else begin
            case(state)
                2'b00: next_state = 2'b10;
                2'b01: next_state = 2'b11;
                2'b10: next_state = bump_right? 2'b11: 2'b10;
                2'b11: next_state = bump_left ? 2'b10: 2'b11;
            endcase
        end
    end

    always@(posedge clk,posedge areset)begin
        if(areset) state <= 2'b11;
        else state <= next_state;
    end

    assign walk_left = &state;
    assign walk_right = state[1] & ~state[0];
    assign aaah = ~state[1];
endmodule


Lemmings 3⚓︎

Website: https://hdlbits.01xz.net/wiki/Lemmings3

這題是上題的延伸,主要是dig的條件要多寫,然後如果照著fsm格式寫應該會快樂不少。

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 ); 
    //right 3'b000, left 3'b001, bump right 3'b010, bump left 3'b011, dig right 3'b100, dig left 3'b101
    reg [2:0] state,next_state;

    always@(*)begin
        case(state)
            3'b000: next_state= ground? (dig? 3'b100: (bump_right? 3'b001:3'b000)): 3'b010;
            3'b001: next_state= ground? (dig? 3'b101: (bump_left ? 3'b000:3'b001)): 3'b011;
            3'b010: next_state= ground? 3'b000: 3'b010;
            3'b011: next_state= ground? 3'b001: 3'b011;
            3'b100: next_state= ground? 3'b100: 3'b010;
            3'b101: next_state= ground? 3'b101: 3'b011;
            default: next_state= 3'bxxx;
        endcase
    end

    always@(posedge clk,posedge areset)begin
        if(areset) state <= 3'b001;
        else state <= next_state;
    end

    assign walk_left = ~state[2] & ~state[1] & state[0];
    assign walk_right = &(~state);
    assign aaah = ~state[2] & state[1];
    assign digging = state[2];
endmodule


Lemmings 4⚓︎

Website: https://hdlbits.01xz.net/wiki/Lemmings4

這題是上題的延伸,也是FSM和counter的結合,這裡只需要注意counter在sequential的logic不要寫錯了,我當時把if(~next_state[2] & next_state[1])寫成if(~state[2] & state[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 ); 
    //right 3'b000, left 3'b001, bump right 3'b010, bump left 3'b011, dig right 3'b100, dig left 3'b101,splatter 3'b110
    reg [2:0] state,next_state;
    reg [7:0] count;

    always@(*)begin
        case(state)
            3'b000: next_state= ground? (dig? 3'b100: (bump_right? 3'b001:3'b000)): 3'b010;
            3'b001: next_state= ground? (dig? 3'b101: (bump_left ? 3'b000:3'b001)): 3'b011;
            3'b010: next_state= ground? ((count>8'd20)? 3'b110: 3'b000): 3'b010;
            3'b011: next_state= ground? ((count>8'd20)? 3'b110: 3'b001): 3'b011;
            3'b100: next_state= ground? 3'b100: 3'b010;
            3'b101: next_state= ground? 3'b101: 3'b011;
            3'b110: next_state = 3'b110;
            default: next_state= 3'bxxx;
        endcase
    end

    always@(posedge clk,posedge areset)begin
        if(areset)begin
            state <= 3'b001;
            count <= 8'd0;
        end
        else begin
            state <= next_state;
            if(~next_state[2] & next_state[1])
                count <= count + 8'd1;
            else
                count <= 8'd0;
        end
    end

    assign walk_left = ~state[2] & ~state[1] & state[0];
    assign walk_right = &(~state);
    assign aaah = ~state[2] & state[1];
    assign digging = state[2] & ~state[1];
endmodule


One-hot FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_onehot

這題不用寫DFF,而且又是one hot vector,所以很適合用assign來寫完transition logic。

Verilog
module top_module(
    input in,
    input [9:0] state,
    output [9:0] next_state,
    output out1,
    output out2);
    //next state
    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];
    //out
    assign out1 = state[8]| state[9];
    assign out2 = state[7]| state[9];
endmodule


PS/2 packet parser⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_ps2

這題有點edge detection的感覺,或許可以開3個reg存前3回合的輸入,不過用FSM可以更理想的省空間。

Verilog
module top_module(
    input clk,
    input [7:0] in,
    input reset,    // Synchronous reset
    output done); //
    //2'b00 -> reset
    //2'b01 -> get the 1xx
    //2'b11 -> output done = 1
    reg [1:0]state, next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            2'b00: next_state = in[3]? 2'b01: 2'b00;
            2'b01: next_state = 2'b10;
            2'b10: next_state = 2'b11;
            2'b11: next_state = in[3]? 2'b01: 2'b00;
        endcase
    end
    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset) state <= 2'b00;//reset
        else state <= next_state;
    end
    // Output logic
    assign done = state[1] & state [0];//done when state== 2'b11
endmodule


PS/2 packet parser and datapath⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_ps2data

這題延續上題,就只是開個datapath來存過往資料。

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
    //2'b00 -> reset
    //2'b01 -> get the 1xx
    //2'b11 -> output done = 1
    reg [1:0]state, next_state;
    // State transition logic (combinational)
    always@(*)begin
        case(state)
            2'b00: next_state = in[3]? 2'b01: 2'b00;
            2'b01: next_state = 2'b10;
            2'b10: next_state = 2'b11;
            2'b11: next_state = in[3]? 2'b01: 2'b00;
        endcase
    end
    // State flip-flops (sequential)
    always@(posedge clk)begin
        if(reset) state <= 2'b00;//reset
        else state <= next_state;
    end
    // Output logic
    assign done = state[1] & state [0];//done when state== 2'b11

    // New: Datapath to store incoming bytes.
    reg [7:0] in1, in2, in3;
    always@(posedge clk)begin
        in1 <= in;
        in2 <= in1;
        in3 <= in2;
    end

    assign out_bytes = done? {in3, in2, in1}: {24{1'b0}};

endmodule


Serial receiver⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_serial

這題單純考怎麼將應用題轉成FSM。

Verilog
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output done
); 
    //data*8 + start + stop + idle + ??? = 12state
    reg[3:0] state, next_state;
    always@(*)begin
        case(state)
            4'd0: next_state = in? 4'd0: 4'd1;//idle
            4'd1: next_state = 4'd2;//start
            4'd2: next_state = 4'd3;//data1
            4'd3: next_state = 4'd4;//data2
            4'd4: next_state = 4'd5;//data3
            4'd5: next_state = 4'd6;//data4
            4'd6: next_state = 4'd7;//data5
            4'd7: next_state = 4'd8;//data6
            4'd8: next_state = 4'd9;//data7
            4'd9: next_state = in? 4'd10: 4'd11;//data8
            4'd10: next_state = in? 4'd0: 4'd1;//stop
            4'd11: next_state = in? 4'd0: 4'd11;//???
            default: next_state = 4'bxxxx;
        endcase
    end

    assign done = (state == 4'd10);

    always@(posedge clk)begin
        if(reset) state <= 4'b0000;
        else state <= next_state;
    end
endmodule


Serial receiver and datapath⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_serialdata

這題接續上題,多加一個datapath存資料。

Verilog
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

    // Use FSM from Fsm_serial
    //data*8 + start + stop + idle + ??? = 12state
    reg[3:0] state, next_state;
    always@(*)begin
        case(state)
            4'd0: next_state = in? 4'd0: 4'd1;//idle
            4'd1: next_state = 4'd2;//start
            4'd2: next_state = 4'd3;//data1
            4'd3: next_state = 4'd4;//data2
            4'd4: next_state = 4'd5;//data3
            4'd5: next_state = 4'd6;//data4
            4'd6: next_state = 4'd7;//data5
            4'd7: next_state = 4'd8;//data6
            4'd8: next_state = 4'd9;//data7
            4'd9: next_state = in? 4'd10: 4'd11;//data8
            4'd10: next_state = in? 4'd0: 4'd1;//stop
            4'd11: next_state = in? 4'd0: 4'd11;//???
            default: next_state = 4'bxxxx;
        endcase
    end

    assign done = (state == 4'd10);

    always@(posedge clk)begin
        if(reset) state <= 4'b0000;
        else state <= next_state;
    end
    // New: Datapath to latch input bits.
    reg [8:0] data;
    always@(posedge clk)begin
        data <= {in,data[8:1]};
    end
    assign out_byte = data[7:0];
endmodule


Serial receiver with parity checking⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_serialdp

這題接續上題,data input從8 bit變9 bit,所以FSM要改。然後有個細節要注意,就是parity的reset等到start階段時也要reset。至於說如何判別is_start,這裡得用assign is_start = (next_state == 4'd1);,不能用assign is_start = (state == 4'd1);的原因在於,會晚一個cycle。所以把握一個原則,sequential logic中若用到狀態,記得要寫next_state。

Verilog
module top_module(
    input clk,
    input in,
    input reset,    // Synchronous reset
    output [7:0] out_byte,
    output done
); //

    // Modify FSM and datapath from Fsm_serialdata
    // Use FSM from Fsm_serial
    //data*8 + start + stop + idle + ??? = 12state
    reg[3:0] state, next_state;
    always@(*)begin
        case(state)
            4'd0: next_state = in? 4'd0: 4'd1;//idle
            4'd1: next_state = 4'd2;//start
            4'd2: next_state = 4'd3;//data1
            4'd3: next_state = 4'd4;//data2
            4'd4: next_state = 4'd5;//data3
            4'd5: next_state = 4'd6;//data4
            4'd6: next_state = 4'd7;//data5
            4'd7: next_state = 4'd8;//data6
            4'd8: next_state = 4'd9;//data7
            4'd9: next_state = 4'd10;//data8
            4'd10: next_state = in? 4'd11: 4'd12;//data9
            4'd11: next_state = in? 4'd0: 4'd1;//stop
            4'd12: next_state = in? 4'd0: 4'd12;//???
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= 4'b0000;
        else begin
        state <= next_state;
        valid <= odd;
        end
    end
    // New: Datapath to latch input bits.
    reg [9:0] data;
    always@(posedge clk)begin
        data <= {in,data[9:1]};
    end

    // New: Add parity checking.
    wire odd,is_start;
    assign is_start = (next_state == 4'd1);
    parity pr(.clk(clk),.reset(reset|is_start),.in(in),.odd(odd));
    reg valid;

    assign out_byte = valid? data[7:0]: 8'd0;
    assign done = (state == 4'd11) & valid;
endmodule


Sequence recognition⚓︎

Website: https://hdlbits.01xz.net/wiki/Fsm_hdlc

這題分別對連續5,6,7以上個1做判斷,並做相對應的輸出,其實很像進階版的edge detection,不過可以用FSM實現,可以少幾個register。

Verilog
module top_module(
    input clk,
    input reset,    // Synchronous reset
    input in,
    output disc,
    output flag,
    output err);
    reg [3:0] state, next_state;
    parameter none = 4'd0;
    parameter one = 4'd1;
    parameter two = 4'd2;
    parameter three = 4'd3;
    parameter four = 4'd4;
    parameter five = 4'd5;
    parameter six = 4'd6;
    parameter seven = 4'd7;
    parameter discard = 4'd8;
    parameter fg = 4'd9;

    always@(*)begin
        case(state)
            none: next_state = in? one: none;
            one: next_state = in? two: none;
            two: next_state = in? three: none;
            three: next_state = in? four: none;
            four: next_state = in? five: none;
            five: next_state = in? six: discard;
            six: next_state = in? seven: fg;
            seven: next_state = in? seven: none;
            discard: next_state = in? one: none;
            fg: next_state = in? one: none;
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= none;
        else state <= next_state;
    end

    assign disc = (state == discard);
    assign flag = (state == fg);
    assign err = (state == seven);
endmodule


Q8: Design a Mealy FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2013_q8

這題應該是這網站上第一題明確指出需使用mealy machine的題目。

Verilog
module top_module (
    input clk,
    input aresetn,    // Asynchronous active-low reset
    input x,
    output z ); 
    reg [1:0] state, next_state;
    parameter zero_bit = 2'b00;
    parameter one_bit = 2'b01;
    parameter two_bit = 2'b10;

    always@(*)begin
        case(state)
            zero_bit: next_state = x? one_bit: zero_bit;
            one_bit: next_state = x? one_bit: two_bit;
            two_bit: next_state = x? one_bit: zero_bit;
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk, negedge aresetn)begin
        if(~aresetn) state <= zero_bit;
        else state <= next_state;
    end

    assign z = (state == two_bit) && x;
endmodule


Q5a: Serial two's complementer (Moore FSM)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q5a

這題用moore machine寫2補數,就只有lsb的1輸出改1,沒什麼太難的。

Verilog
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    reg [1:0] state, next_state;
    parameter idle = 2'b00;
    parameter zero = 2'b01;
    parameter one = 2'b10;

    always@(*)begin
        case(state)
            idle: next_state = x? zero: idle;
            zero: next_state = x? one: zero;
            one: next_state = x? one: zero;
            default: next_state = 2'bxx;
        endcase
    end

    always@(posedge clk, posedge areset)begin
        if(areset) state <= 2'b00;
        else state <= next_state;
    end

    assign z = (state == zero);
endmodule


Q5b: Serial two's complementer (Mealy FSM)⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/ece241_2014_q5b

這題用mealy machine,因為mealy machine比moore machine少一個state,所以輸出早一個週期。

Verilog
module top_module (
    input clk,
    input areset,
    input x,
    output z
); 
    reg state, next_state;
    parameter idle = 1'b0;
    parameter comp = 1'b1;

    assign next_state = state | x;

    always@(posedge clk,posedge areset)begin
        if(areset) state = idle;
        else state = next_state;
    end

    assign z = (state & ~x) | (~state & x);
endmodule


Q3a: FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2014_q3fsm

這題在考怎麼算三個cycle內有兩個1,其實可以開個datapath,然後取xnor和or。然後有個細節要注意,就是當reset和A轉換為B時要將datapath更新成3'b000,這裡得寫else if(state == A) temp <= 3'b000;而不是寫else if(next_state == B) temp <= 3'b000;的原因在於,next_state == B也可能代表next_state == D

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);  
    reg [1:0] state, next_state;
    parameter A = 2'b00;
    parameter B = 2'b01;
    parameter C = 2'b10;
    parameter D = 2'b11;

    always@(*)begin
        case(state)
            A: next_state = s? B: A;
            B: next_state = C;
            C: next_state = D;
            D: next_state = B;
        endcase
    end

    reg [2:0]temp;
    always@(posedge clk)begin 
        if(reset) state <= A;
        else state <= next_state;
    end

    always@(posedge clk)begin 
        if(reset) temp <= 3'b000;
        else if(state == A) temp <= 3'b000;
        else temp <= {temp[1:0],w};
    end

    assign z = (state == B) && ~(^temp) && (|temp);
endmodule


Q3b: FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2014_q3bfsm

這題就照table寫Moore Machine,沒什麼難度。

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous reset
    input x,
    output z
);
    reg [2:0] state, next_state;

    always@(*)begin
        case(state)
            3'b000: next_state = x? 3'b001: 3'b000;
            3'b001: next_state = x? 3'b100: 3'b001;
            3'b010: next_state = x? 3'b001: 3'b010;
            3'b011: next_state = x? 3'b010: 3'b001;
            3'b100: next_state = x? 3'b100: 3'b011;
            default: next_state = 3'bxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= 3'b000;
        else state <= next_state;
    end

    assign z = (~state[2]& state[1] & state[0]) | (state[2]& ~state[1] & ~state[0]);
endmodule


Q3c: FSM logic⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2014_q3c

這題因為有input clk,差點寫矇了,實際上因為這題的y是input給的,所以完全不用使用sequential block,也就用不上clk。

Verilog
module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    reg [2:0] next_state;

    always@(*)begin
        case(y)
            3'b000: next_state = x? 3'b001: 3'b000;
            3'b001: next_state = x? 3'b100: 3'b001;
            3'b010: next_state = x? 3'b001: 3'b010;
            3'b011: next_state = x? 3'b010: 3'b001;
            3'b100: next_state = x? 3'b100: 3'b011;
            default: next_state = 3'bxxx;
        endcase
    end

    assign Y0 = next_state[0];
    assign z = (~y[2]& y[1] & y[0]) | (y[2]& ~y[1] & ~y[0]);
endmodule


Q6b: FSM next-state logic⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q6b

這題就照著FSM圖表寫完code就結束了,水題一題。

Verilog
module top_module (
    input [3:1] y,
    input w,
    output Y2);
    parameter A = 3'd0;
    parameter B = 3'd1;
    parameter C = 3'd2;
    parameter D = 3'd3;
    parameter E = 3'd4;
    parameter F = 3'd5;

    reg [3:1]next_state;
    always@(*)begin
        case(y)
            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 = 3'bxxx;
        endcase
    end
    assign Y2 = next_state[2];
endmodule


Q6c: FSM one-hot next-state logic⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q6c

這題跟上題很像,不過改成用assign完成,有關one hot vector一律建議使用assign。

Verilog
module top_module (
    input [6:1] y,
    input w,
    output Y2,
    output Y4);   
    assign Y2 = ~w & y[1];
    assign Y4 = w & (y[2] | y[3] | y[5] | y[6]);
endmodule


Q6: FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/m2014_q6

這題就是上上題的完整版,把sequential logic寫完就結束了。

Verilog
module top_module (
    input clk,
    input reset,     // synchronous reset
    input w,
    output z);
    parameter A = 3'd0;
    parameter B = 3'd1;
    parameter C = 3'd2;
    parameter D = 3'd3;
    parameter E = 3'd4;
    parameter F = 3'd5;

    reg [2:0] state,next_state;
    always@(*)begin
        case(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 = 3'bxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= A;
        else state <= next_state;
    end

    assign z = state[2] & ~state[1];
endmodule


Q2a: FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2012_q2fsm

這題就是上題把input w complement,所以很容易就寫完。

Verilog
module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    input w,
    output z
);
    parameter A = 3'd0;
    parameter B = 3'd1;
    parameter C = 3'd2;
    parameter D = 3'd3;
    parameter E = 3'd4;
    parameter F = 3'd5;

    reg [2:0] state,next_state;
    always@(*)begin
        case(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 = 3'bxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= A;
        else state <= next_state;
    end

    assign z = state[2] & ~state[1];
endmodule


Q2b: One-hot FSM equations⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2012_q2b

這題就是上上上題把input w complement,所以很容易就寫完。

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


Q2a: FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2013_q2afsm

這題就是照著圖寫FSM,沒什麼太多的技巧。

Verilog
module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input [3:1] r,   // request
    output [3:1] g   // grant
); 

    reg [1:0] state, next_state;
    parameter A = 2'b00;
    parameter B = 2'b01;
    parameter C = 2'b10;
    parameter D = 2'b11;

    always@(*)begin
        case(state)
            A:begin
                if(~|r) next_state = A;
                else if(r[3:1] == 3'b100) next_state = D;
                else if(r[2:1] == 2'b10) next_state = C;
                else if(r[1]) next_state = B;
                else next_state = 2'bxx;
            end
            B: next_state = r[1]? B: A;
            C: next_state = r[2]? C: A;
            D: next_state = r[3]? D: A;
        endcase
    end

    always@(posedge clk)begin
        if(~resetn) state <= A;
        else state <= next_state;
    end

    assign g = {(state == D), (state == C), (state == B)};
endmodule


Q2b: Another FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/2013_q2bfsm

這題就是照著題目敘述寫FSM,考的是英文能力和debug通靈技巧。

Verilog
module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 
    reg [3:0]state, next_state;
    parameter A = 4'd0;
    parameter f_1 = 4'd1;
    parameter zero_bit = 4'd2;
    parameter one_bit = 4'd3;
    parameter two_bit = 4'd4;
    parameter three_bit = 4'd5;
    parameter g_0 = 4'd6;
    parameter g_1 = 4'd7;
    parameter temp = 4'd8;

    always@(*)begin
        case(state)
            A: next_state = f_1;
            f_1: next_state = zero_bit;
            zero_bit: next_state = x? one_bit: zero_bit;
            one_bit: next_state = x?  one_bit: two_bit;
            two_bit: next_state = x? three_bit: zero_bit;
            three_bit: next_state = y? g_1: temp;
            g_0: next_state = g_0;
            temp: next_state = y? g_1: g_0;
            g_1: next_state = g_1;
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk)begin
        if(~resetn) state <= A;
        else state <= next_state;
    end

    assign f = (state == f_1);
    assign g = (state == three_bit) | (state == temp) | (state == g_1);
endmodule


Building Larger Circuits⚓︎

Counter with period 1000⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_count1k

這題只是看起來位數很多很嚇人,如果熟練的話可以寫得很簡潔。

Verilog
module top_module (
    input clk,
    input reset,
    output reg[9:0] q);
    always@(posedge clk)begin
        if(reset) q <= 10'd0;
        else if(q == 10'd999) q <= 10'd0;
        else q <= q + 1'b1;
    end
endmodule


4-bit shift register and down counter⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_shiftcount

這題我覺得也說不上是特別複雜的電路,前面更多更複雜的題目,我猜是因為幫後面題目鋪墊的關係。

Verilog
module top_module (
    input clk,
    input shift_ena,
    input count_ena,
    input data,
    output reg[3:0] q);
    always@(posedge clk)begin
        case({shift_ena, count_ena})
            2'b00: q <= q;
            2'b01: q <= q - 1'b1;
            2'b10: q <= {q[2:0],data};
            2'b11: q <= 4'bxxxx;
        endcase
    end
endmodule


FSM: Sequence 1101 recognizer⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsmseq

這題我覺得也說不上是特別複雜的電路,前面更多更複雜的題目,我猜是因為幫後面題目鋪墊的關係。

Verilog
module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output start_shifting);
    reg [2:0] state, nstate;
    parameter zero = 3'd0;
    parameter one = 3'd1;
    parameter two = 3'd2;
    parameter three = 3'd3;
    parameter four = 3'd4;

    always@(*)begin
        case(state)
            zero: nstate = data? one: zero;
            one: nstate = data? two: zero;
            two: nstate = data? two: three;
            three: nstate = data? four: zero;
            four: nstate = four;
            default: nstate = 3'bxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= zero;
        else state <= nstate;
    end

    assign start_shifting = (state == four);

endmodule


FSM: Enable shift register⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsmshift

這題我覺得也說不上是特別複雜的電路,前面更多更複雜的題目,我猜是因為幫後面題目鋪墊的關係。

Verilog
module top_module (
    input clk,
    input reset,      // Synchronous reset
    output shift_ena);
    reg [2:0] counter; 

    always@(posedge clk)begin
        if(reset) counter <= 3'd0;
        else if(counter == 3'd4) counter <= counter;
        else counter <= counter + 1'b1;
    end

    assign shift_ena = ~counter[2];
endmodule


FSM: The complete FSM⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsm

這題就是前三題的綜合,如果已經寫過Lemmings4,應該覺得這題佛心來著。

Verilog
module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output shift_ena,
    output counting,
    input done_counting,
    output done,
    input ack );
    reg [3:0] state, nstate;
    parameter re = 4'd0;
    parameter l = 4'd1;
    parameter ll = 4'd2;
    parameter llo = 4'd3;
    parameter llol = 4'd4;
    parameter s1 = 4'd5;
    parameter s2 = 4'd6;
    parameter s3 = 4'd7;
    parameter is_counting = 4'd8;
    parameter is_done = 4'd9;

    always@(*)begin
        case(state)
            re: nstate = data? l: re;
            l: nstate = data? ll: re;
            ll: nstate = data? ll: llo;
            llo: nstate = data? llol: re;
            llol: nstate = s1;
            s1: nstate = s2;
            s2: nstate = s3;
            s3: nstate = is_counting;
            is_counting: nstate = done_counting? is_done: is_counting;
            is_done: nstate = ack? re: is_done;
            default: nstate = 4'bxxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= re;
        else state <= nstate;
    end

    assign shift_ena = (state == s1) | (state == s2) | (state == s3) | (state == llol);
    assign counting = (state == is_counting);
    assign done = (state == is_done);

endmodule


The complete timer⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fancytimer

這題單純在比耐心和debug能力,順便考驗怎麼省空間,我也覺得delay透過倒數的方式,可能空間可以少不少。

Verilog
module top_module (
    input clk,
    input reset,      // Synchronous reset
    input data,
    output [3:0] count,
    output counting,
    output done,
    input ack );

    //FSM
    reg [3:0] state,next_state;

    parameter re = 4'd0;
    parameter l = 4'd1;
    parameter ll = 4'd2;
    parameter llo = 4'd3;
    parameter shift_o = 4'd4;
    parameter shift_l = 4'd5;
    parameter shift_lo = 4'd6;
    parameter shift_ll = 4'd7;
    parameter is_count = 4'd8;
    parameter is_finish = 4'd9;

    always@(*)begin
        case(state)
            re: next_state = data ? l: re;
            l: next_state = data? ll: re;
            ll: next_state = data? ll: llo;
            llo: next_state = data? shift_o: re;
            shift_o: next_state = shift_l;
            shift_l: next_state = shift_lo;
            shift_lo: next_state = shift_ll;
            shift_ll: next_state = is_count;
            is_count: next_state = ((num == 15'd999)&(data_pipe == 4'd0))? is_finish: is_count;
            is_finish: next_state = ack? re: is_finish;
            default: next_state = 4'bxxxx;
        endcase
    end

    always@(posedge clk)begin
        if(reset) state <= re;
        else state <= next_state;
    end

    //Counter
    reg [9:0] num;
    always@(posedge clk)begin
        if(reset) num <= 10'd0;
        else if(num == 10'd999) num <= 10'd0;
        else if(counting) num <= num +10'd1;
        else num <= num;
    end
    //Data
    wire is_data_shift;
    reg [3:0] data_pipe;
    assign is_data_shift = (state == shift_o) | (state == shift_l) | (state == shift_lo) | (state == shift_ll);
    always@(posedge clk)begin
        if(reset) data_pipe <= 4'd0;
        else if(is_data_shift) data_pipe <= {data_pipe[2:0], data};
        else if(num == 10'd999) data_pipe <= data_pipe - 1'b1;
        else data_pipe <= data_pipe;
    end
    assign count = data_pipe;
    assign counting = (state == is_count);
    assign done = (state == is_finish);
endmodule


FSM: One-hot logic equations⚓︎

Website: https://hdlbits.01xz.net/wiki/Exams/review2015_fsmonehot

這題跟上題比,不需要考慮clock,要用assign接,滿容易的。

Verilog
module top_module(
    input d,
    input done_counting,
    input ack,
    input [9:0] state,    // 10-bit one-hot current state
    output B3_next,
    output S_next,
    output S1_next,
    output Count_next,
    output Wait_next,
    output done,
    output counting,
    output shift_ena
); //

    // You may use these parameters to access state bits using e.g., state[B2] instead of state[6].
    parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
    assign B3_next = state[B2];
    assign S_next = (state[Wait] & ack) | (state[S] & ~d) | (state[S1] & ~d) | (state[S110] & ~d);
    assign S1_next = state[S] & d;
    assign Count_next = state[B3] | (state[Count] & ~done_counting);
    assign Wait_next = (state[Count] & done_counting) | (state[Wait] & ~ack);
    assign done = state[Wait];
    assign counting = state[Count];
    assign shift_ena = state[B0] | state[B1] | state[B2] | state[B3];
endmodule


Verification: Reading Simulations⚓︎

Finding bugs in code⚓︎

Mux⚓︎

Website: https://hdlbits.01xz.net/wiki/Bugs_mux2

終於到了要debug的題型了,這部分相對先前的題型友善許多,這題的bug出在output要改成8bit,還有用三元運算可能方便一點。

Verilog
module top_module (
    input sel,
    input [7:0] a,
    input [7:0] b,
    output [7:0] out  );

    assign out = sel? a: b;

endmodule


NAND⚓︎

Website: https://hdlbits.01xz.net/wiki/Bugs_nand3

這題要寫nand,所以最後要接個not gate,然後要使用submodule的話,參數要馬照順序給,要馬照名字給。

Verilog
module top_module (input a, input b, input c, output out);//
    wire out_inv;
    andgate inst1 ( .out(out_inv), .a(a), .b(b), .c(c), .d(1'b1), .e(1'b1) );
    assign out = ~out_inv;
endmodule


Mux(2)⚓︎

Website: https://hdlbits.01xz.net/wiki/Bugs_mux4

這題問題出在wire沒開vector,sel亂接,還有變數重複命名。

Verilog
module top_module (
    input [1:0] sel,
    input [7:0] a,
    input [7:0] b,
    input [7:0] c,
    input [7:0] d,
    output [7:0] out  ); //

    wire [7:0]mux0, mux1;
    mux2 mux_0 ( sel[0],    a,    b, mux0 );
    mux2 mux_1 ( sel[0],    c,    d, mux1 );
    mux2 mux_2 ( sel[1], mux0, mux1,  out );

endmodule


Add/sub⚓︎

Website: https://hdlbits.01xz.net/wiki/Bugs_addsubz

這題問題出在他把logical not和arithmetic not搞混了,還有沒寫else,會產生latch。

Verilog
// synthesis verilog_input_version verilog_2001
module top_module ( 
    input do_sub,
    input [7:0] a,
    input [7:0] b,
    output reg [7:0] out,
    output reg result_is_zero
);//

    always @(*) begin
        case (do_sub)
          0: out = a+b;
          1: out = a-b;
        endcase

        if (!out)
            result_is_zero = 1;
        else result_is_zero = 0;
    end

endmodule


Case statement⚓︎

Website: https://hdlbits.01xz.net/wiki/Bugs_case

這題問題出在他進位亂寫,bit亂寫,改一下就結束了。

Verilog
module top_module (
    input [7:0] code,
    output reg [3:0] out,
    output reg valid=1'b1 );//

     always @(*)
        case (code)
            8'h45: out = 4'd0;
            8'h16: out = 4'd1;
            8'h1e: out = 4'd2;
            8'h26: out = 4'd3;
            8'h25: out = 4'd4;
            8'h2e: out = 4'd5;
            8'h36: out = 4'd6;
            8'h3d: out = 4'd7;
            8'h3e: out = 4'd8;
            8'h46: out = 4'd9;
            default: out = 4'd0;
        endcase
    always@(*)begin
        if(!(code == 8'h45) & !(out))
            valid = 1'b0;
        else
            valid = 1'b1;
    end
endmodule


Build a circuit from a simulation waveform⚓︎

Combinational circuit 1⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit1

這系列是看波形寫code,也滿快樂的。

Verilog
module top_module (
    input a,
    input b,
    output q );//

    assign q = a & b;
endmodule


Combinational circuit 2⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit2

這題單純就是觀察有偶數個input時,output是1,所以就是xnor gate。

Verilog
module top_module (
    input a,
    input b,
    input c,
    input d,
    output q );//

    assign q = ~(a ^ b ^ c ^ d);

endmodule


Combinational circuit 3⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit3

這題單純就是觀察,當非c且非d,或非a且非b時,輸出為0。反過來說,當c或d,且a或b時,輸出為1。

Verilog
module top_module (
    input a,
    input b,
    input c,
    input d,
    output q );//

    assign q = (a | b) & (c | d);

endmodule


Combinational circuit 4⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit4

這題單純就是觀察,當b或c時,輸出為1。

Verilog
module top_module (
    input a,
    input b,
    input c,
    input d,
    output q );//

    assign q = b | c; // Fix me

endmodule


Combinational circuit 5⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit5

透過觀察可以知道,當c是0,1,2,3時,對應的輸入為b,e,a,d四個input,否則output 4'hf,或是說是4'b1111。

Verilog
module top_module (
    input [3:0] a,
    input [3:0] b,
    input [3:0] c,
    input [3:0] d,
    input [3:0] e,
    output reg [3:0] q );
    always@(*)begin
        case(c)
            4'd0: q = b;
            4'd1: q = e;
            4'd2: q = a;
            4'd3: q = d;
            default: q = 4'hf;
        endcase
    end
endmodule


Combinational circuit 6⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit6

透過觀察可以知道,這題有點像是decoder,不過有指定的輸出。

Verilog
module top_module (
    input [2:0] a,
    output [15:0] q ); 
    always@(*)begin
        case(a)
            3'd0: q = 16'h1232;
            3'd1: q = 16'haee0;
            3'd2: q = 16'h27d4;
            3'd3: q = 16'h5a0e;
            3'd4: q = 16'h2066;
            3'd5: q = 16'h64ce;
            3'd6: q = 16'hc526;
            3'd7: q = 16'h2f19;
        endcase
    end
endmodule


Sequential circuit 7⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit7

透過觀察可以知道,這題就是q就是a接了inverter,只不過晚一回合輸出。

Verilog
module top_module (
    input clk,
    input a,
    output q );
    reg state, next_state;
    parameter zero_1 = 1'd0;
    parameter one_1 = 1'd1;

    always@(*)begin
        next_state = a? one_1: zero_1;
    end

    always@(posedge clk)begin
        state <= next_state;
    end

    assign q = ~state;
endmodule


Sequential circuit 8⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit8

q的話很容易看出來是negetive edge的d flip-flop,p的話就是要觀察到是latch結構。

Verilog
module top_module (
    input clock,
    input a,
    output p,
    output reg q );
    assign p = clock? a: p;
    always@(negedge clock)begin
        q <= a;
    end
endmodule


Sequential circuit 9⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit9

這題能觀察出是個計時器結構。

Verilog
module top_module (
    input clk,
    input a,
    output reg[3:0] q );
    always@(posedge clk)begin
        if(a) q <= 4'd4;
        else if(q == 4'd6) q <= 4'd0;
        else q <= q + 1'd1;
    end
endmodule


Sequential circuit 10⚓︎

Website: https://hdlbits.01xz.net/wiki/Sim/circuit10

這題要想成是一台FSM,然後好好觀察在不同state和input下時,state的輸出。

Verilog
module top_module (
    input clk,
    input a,
    input b,
    output reg q,
    output reg state  );
    reg next_state;
    always@(*)begin
        case(state)
            1'b0: next_state = a & b;
            1'b1: next_state = a | b;
        endcase
    end
    always@(posedge clk)begin
        state <= next_state;
    end

    assign q = state ^ a ^ b;
endmodule


Verification: Writing Testbenches⚓︎

Clock⚓︎

Website: https://hdlbits.01xz.net/wiki/Tb/clock

這題是hdlbits第一次讓人練習testbench,所以就講詳細點。
第一行的格式是`timescale 時間單位/時間精度
像說下列的程式有講到#5,代表delay5個時間單位,然後這裡的時間單位就是5ps。
然後時間精度的話,代表說模擬的最小尺度,可以粗略的理解成像是c++的floating point,最小最小只能觀察到的尺度,像程式碼這裡最小尺度就是1ps。
有關timescale的說明,可以多看這個網站: https://www.chipverify.com/verilog/verilog-timescale

然後在testbench中,給submodule的input用reg,接收submodule的output用wire。原因在於,對於submodule來說的input,對testbench來說是output,對於submodule來說的output,對於testbench是input。

然後initial裡面放初始化數值,然後這個題目要無限重複clk,所以不用寫$finish

Verilog
`timescale 1ps/1ps
module top_module ( );
    reg clk;
    initial begin
        clk = 1'b0;
    end
    always #5 clk = ~clk;

    dut inst( .clk(clk)) ;
endmodule


Testbench1⚓︎

Website: https://hdlbits.01xz.net/wiki/Tb/tb1

這題不像上題要一直無限clk,可以透過$finish來限制模擬時間。

Verilog
module top_module ( output reg A, output reg B );//

    // generate input patterns here
    initial begin
        A = 1'b0;
        B = 1'b0;
        #10 A = 1'b1;
        #5 B = 1'b1;
        #5 A = 1'b0;
        #20 B = 1'b0;
        #300 $finish;
    end

endmodule


AND gate⚓︎

Website: https://hdlbits.01xz.net/wiki/Tb/and

這題不像上題要一直無限clk,可以透過$finish來限制模擬時間。

Verilog
module top_module();
    reg [1:0]in;
    wire out;
    initial begin
        in = 2'b00;
        #10 in = 2'b01;
        #10 in = 2'b10;
        #10 in = 2'b11;
        #20 $finish;
    end

    andgate and_gate(.in(in), .out(out));
endmodule


Testbench2⚓︎

Website: https://hdlbits.01xz.net/wiki/Tb/tb2

這題reg和wire變多了,可以考慮把initial block分開寫,可讀性較佳。

Verilog
module top_module();
    reg clk, in;
    reg [2:0] s;
    wire out;

    initial begin
        clk = 1'b0;
    end    
    always #5 clk = ~clk;

    initial begin
        in = 1'b0;
        #20 in = 1'b1;
        #10 in = 1'b0;
        #10 in = 1'b1;
        #30 in = 1'b0;
    end

    initial begin
        s = 3'd2;
        #10 s = 3'd6;
        #10 s = 3'd2;
        #10 s = 3'd7;
        #10 s = 3'd0;
    end

    initial begin
        #100 $finish;
    end

    q7 inst(.clk(clk), .in(in), .s(s), .out(out));
endmodule


T flip-flop⚓︎

Website: https://hdlbits.01xz.net/wiki/Tb/tff

這題照著題目要求寫,就結束了。完全不用考慮時間間隔弄多少。

Verilog
module top_module ();
    reg clk;
    reg reset;
    reg t;
    wire q;

    initial begin
        clk = 1'b0;
    end
    always #5 clk = ~clk;

    initial begin
        reset = 1'b1;
        #10 reset = 1'b0;
    end

    initial begin
        t = 1'b0;
        #10 t = 1'b1;
    end

    initial begin
        #100 $finish;
    end

    tff inst(.clk(clk), .reset(reset), .t(t), .q(q));
endmodule


CS450⚓︎

Cs450/timer⚓︎

Website: https://hdlbits.01xz.net/wiki/Cs450/timer

這題單純寫個counter,就結束了。

Verilog
module top_module(
    input clk, 
    input load, 
    input [9:0] data, 
    output tc
);  
    reg [9:0] counter;
    always@(posedge clk)begin
        if(load) counter <= data;
        else if(counter == 10'd0) counter <= 10'd0;
        else counter <= counter - 1'b1;
    end
    assign tc = (counter == 10'd0);
endmodule


Cs450/counter 2bc⚓︎

Website: https://hdlbits.01xz.net/wiki/Cs450/counter_2bc

這題就是照題目寫FSM,沒什麼難度。

Verilog
module top_module(
    input clk,
    input areset,
    input train_valid,
    input train_taken,
    output reg [1:0] state
);
    reg [1:0] next_state;
    parameter SNT = 2'b00;
    parameter WNT = 2'b01;
    parameter WT = 2'b10;
    parameter ST = 2'b11;

    always@(*)begin
        if(train_valid)begin
            case(state)
                SNT: next_state= train_taken? WNT: SNT;
                WNT: next_state= train_taken? WT: SNT;
                WT: next_state= train_taken? ST: WNT;
                ST: next_state= train_taken? ST: WT;
            endcase
        end
        else next_state = state;
    end

    always@(posedge clk, posedge areset)begin
        if(areset) state <= WNT;
        else state <= next_state;
    end
endmodule


Cs450/history shift⚓︎

Website: https://hdlbits.01xz.net/wiki/Cs450/history_shift

這題就是簡單版的預測分支,題目很長,實際上滿簡單的,考驗英文能力。

Verilog
module top_module(
    input clk,
    input areset,

    input predict_valid,
    input predict_taken,
    output reg [31:0] predict_history,

    input train_mispredicted,
    input train_taken,
    input [31:0] train_history
);
    always@(posedge clk, posedge areset)begin
        if(areset) predict_history <= 32'd0;
        else if(train_mispredicted) predict_history <= {train_history[30:0], train_taken};
        else if(predict_valid) predict_history <= {predict_history[30:0], predict_taken};
    end
endmodule


Cs450/gshare⚓︎

Website: https://hdlbits.01xz.net/wiki/Cs450/gshare

這題就前兩題的綜合題,考驗的是英文閱讀能力,

Verilog
module top_module(
    input clk,
    input areset,

    input  predict_valid,
    input  [6:0] predict_pc,
    output predict_taken,
    output [6:0] predict_history,

    input train_valid,
    input train_taken,
    input train_mispredicted,
    input [6:0] train_history,
    input [6:0] train_pc
);
    //update PHT
    reg [1:0] PHT [127:0];
    wire [6:0]hash;
    assign hash = train_pc ^ train_history;
    integer i;    
    always@(posedge clk, posedge areset)begin
        if(areset)begin
            for(i=0; i<128; i++)begin
                PHT[i] <= 2'b01;
            end
        end 
        else begin
            if(train_taken & train_valid) PHT[hash] <= (PHT[hash] == 2'b11)? 2'b11: PHT[hash] + 2'b01;
            else if(~train_taken & train_valid) PHT[hash] <= (PHT[hash] == 2'b00)? 2'b00: PHT[hash] - 2'b01;
        end
    end    

    assign predict_taken = PHT[predict_pc ^ predict_history][1];
    //update predict history
    always@(posedge clk, posedge areset)begin
        if(areset) predict_history <= 7'd0;
        else if(train_valid & train_mispredicted) predict_history <= {train_history[5:0], train_taken};
        else if(predict_valid) predict_history <= {predict_history[5:0], predict_taken};
    end

endmodule