跳轉到

Building Larger Circuits

Counter with period 1000

原題:Counter with period 1000

熟悉計數器寫法後,可以把邏輯寫得很簡潔。

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

原題:4-bit shift register and down counter

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

原題:FSM: Sequence 1101 recognizer

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

原題:FSM: Enable shift register

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

原題:FSM: The complete FSM

整合前三題,FSM 與 datapath 分開處理會比較清楚。

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

原題:The complete timer

重點在 FSM、counter 與輸出控制的整合;delay 可用倒數 counter 實作,狀態會更好管理。

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

原題:FSM: One-hot logic equations

和前一題相比,此題不需要 clock,可直接用 assign 描述 one-hot transition logic。

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