Verilog-时序电路设计

时序电路设计

 状态图描述

module checker(Z, X, clk);
    parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b11, s3 = 2'b10;
    output Z;
    input X, clk;
    reg [1:0] state, next_state;
    reg Z;
    always @(X, state)
        case (state)
            s0:if(X)
                    begin
                        next_state <= s1; Z = 0;
                    end
                else
                    begin
                        next_state <= s0; Z = 0;
                    end
            s1:if(X)
                    begin
                        next_state <= s2; Z = 0;
                    end
                else
                    begin
                        next_state <= s0; Z = 0;
                    end
            s2:if(X)
                    begin
                        next_state <= s3; Z = 1;
                    end
                else
                    begin
                        next_state <= s0; Z = 0;
                    end
            s3:if(X)
                    begin
                        next_state <= s3; Z = 1;
                    end
                else
                    begin
                        next_state <= s0; Z = 0;
                    end
            endcase
        always @(posedge clk)
            state <= next_state;
endmodule

化简描述 

//序列检测器模块
module test (Z, X, clk);
    output Z;
    input X, clk;
    wire w1, w2;
        DFF U1 (.clk(clk), .D(X), .Q(w1));
        DFF U2 (.clk(clk), .D(w1), .Q(w2));
        assign Z = X & w1 & w2;
endmodule


//D触发器模块
module DFF (Q, D, clk);
    output Q;
    input D, clk;
    reg Q;
        always @(posedge clk) Q <= D;
endmodule

 抽象描述方式

module checker (Z, X, clk);
    output Z;
    input X, clk;
    reg [2:0] q;
    reg Z;
    always @(posedge clk)    q<= {q[1:0], X};
    always @(posedge clk)    
        if(q==3'b111)    Z=1;
        else    Z = 0;
endmodule

触发器

最简D触发器

module DFF(q, clk, data_in);
    output q;
    input clk, data_in;
    reg q;
    always @(posedge clk) q <= data_in;
endmodule

带复位端的D触发器 

module DFF_rst (q, clk, reset, data_in);
    output q;
    input clk, reset, data_in;
    reg q;
    always @(posedge clk)
        if (!reset) q <= 0;
        else q <= data_in;
endmodule

复杂功能的D触发器 

module DFF_l(q, clk, resetl, reset2, data_in);
    output q;
    input clk, reset1, reset2, data_in;
    reg q;
        always @(posedge clk)
            if (!reset1) q <= 0;
            else q <= data_in;
        always @(posedge clk or negedge reset2)
            if (!reset2) q <= 0;
            else q <= data_in;
endmodule

T触发器

module TFF(data_out, T, clk, reset);
    output data_out;
    input T, clk, reset;
    reg data_out;
        always @(posedge clk or negedge reset)
            if (!reset) data_out <= 1'b0;
            else if (T) data_out <= ~data_out;
endmodule

计数器

二进制计数器

module comp2bit (Q, clk, reset);
    output Q;
    input clk, reset;
    reg Q;
    always @ (posedge clk or negedge reset)
        if (!reset)
            Q<= 1'b0;
        else
            Q <= ~Q;
endmoduld

任意进制计数器 

        对于M进制的计数器,首先应确定计数器所需触发器的个数。N个触发器对应了 2^n

个状态,应有2^n>M。任意进制计数器选取满足条件的最小N, N为计数器中触发器的个数。

        以十一进制计数器为例,最少需要4个触发器。

module comp_11 (count, clk, reset);
    output [3:0] count;
    input clk, reset;
    reg [3:0] count;
    always @ (posedge clk)
        if(reset) count <= 4'b0000;
        else
        if (count == 4'b1010)
            count <= 4'b0000;
        else
            count <= count+1;
endmodule

移位寄存器

环形移位寄存器

module shiftregistl(D, clk, reset);
    parameter shiftregist_width = 4;
    output [shiftregist_width-1:0] D;
    input clk, reset;
    reg [shiftregist_width-1:0] D;
    always @(posedge clk)
        if (!reset)
            D <= 4'b0000;
        else
            D <= {D[shiftregist_width-2:0], D[shiftregist_width-1]};
endmodule

序列信号发生器

由移位寄存器构成

module signal_maker(out, clk, load, D);
    parameter M = 6;
    output out;
    input clk, load;
    input [M-1:0] D;
    reg [M-1:0] Q;
        initial Q = 6'b100111;
        always @(posedge clk)
            if (load) Q <= D;
            else Q <= {Q[M-2:0], Q[M-1]};
    assign out = Q[M-1];
endmodule

由移位寄存器和组合逻辑电路构成 

        首先确定所需移位寄存器的个数n。因M = 6,故 n>=3。其次确定移位寄存器的6个独立状态。按照移位规律每三位一组,划分6个状态为 100、001、011、111, 111、110。其中状态111重复出现,故取n = 4,并重新划分状态, 得到1001、0011、0111、1111、1110、1100。因此确定n = 4。第三,列态序表和反馈激励函数表,求反馈函数F的表达式。

F= ~Q3 + ~Q1 • ~Q0 +Q3+~Q2

module signal_maker(out, clk, load, D);
    parameter M = 4;
    output out;
    input clk, load;
    input [M-1 :0] D;
    reg [M-1:0] Q;
        wire w1;
        always @(posedge clk) //时序电路部分,移位寄存器
            if (load) Q<=D;
            else Q <= {Q[M-2:0], w1};
    assign w1 =(~Q[3])|(~Q[1]&(~Q[0]))|(Q[3]&(~Q[2])); //组合逻辑电路,反馈网络
    assign out =Q[M-1];
endmodule

由计数器构成

module signal_maker(out, clk, reset);
    parameter M = 3;
    output out;
    input clk, reset;
    reg [M-l:0] counter;
        always @(posedge clk)
            if (!reset) counter <= 3'b000;
            else counter <= counter+1;
    assign out = counter[2]|((~counter[1])&(~counter[0]))l(counter[1]&counter[0]);
endmodule

有限同步状态机

        Mealy型状态机的输出与当前状态和输入有关

        Moore型状态机的输出仅依赖于当前状态, 而与输入无关

状态机的编码方式:

  • 二进制编码:其状态寄存器是由触发器组成的。
  • 格雷编码:格雷编码状态跳转时只有一个bit(位)发生变化,减少了产生毛刺和一些暂态的可能。
  • 一位独热编码:这是对于n个状态采用n个bit(位)来编码,每个状态编码中只有一个bit(位)为1,如0001、0010、0100、1000。

状态机的两段式描述方法:

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @(posedge clk or negedge rst_n) //异步复位
    if(!rst_n) current_state <= IDLE;
    else current_state <= next_state; //注意,使用的是非阻塞赋值 
//第二个进程,组合逻辑   always模块,描述状态转移条件判断
    always @(current_state or 输入信号) //电平触发
        begin
            next_state = x; //要初始化,使得系统复位后能进入正确的状态
                case(current_state)
                    Sl:if(...)
                        next_state = S2;    //阻塞赋值
                    outl <= 1'bl;      //注意是非阻塞逻辑
        ...
                endcase
        end

状态机的三段式描述方法:

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器 
always @(posedge clk or negedge rst_n)    //异步复位
    if(!rst_n) current_state <= IDLE;
    else current_state <= next_state;     //注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断
always @(current_state or 输入信号)    //电平触发
    begin
        next_state = x;    //要初始化,使得系统复位后能进入正确的状态
        case(current_state)
            S1: if(...)
            next_state = S2;    //阻塞赋值
        ...   
        endcase
    end
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
    begin
    ...//初始化
        case(next_state or 输入信号)
            S1:
                outl <= 1'bl; //注意是非阻塞逻辑
            S2:
                outl <= 1'b0;
            default:... //default的作用是免除综合工具综合出锁存器
        endcase
    end

4位顺序脉冲发生器

module state4(OUT, clk, rst_n);
    output [3:0] OUT:
    input clk;
    input rst_n;
    reg [3:0] OUT;
    reg [1:0] STATE, next_STATE;
    always @(STATE)
        case (STATE)
            2'b00:
                begin
                    OUT <= 4'b11000;
                    next_STATE <= 2'b01;
            2'b01:
                begin
                    OUT <= 4'b0100;
                    next_STATE <= 2'b10;
                end
            2'b10:
                begin
                    OUT<= 4'b0010;
                    next_STATE <= 2'b11;
                end
            2'bll:
                begin
                    OUT <= 4'b0001;
                    next_STATE <= 2'b00;
                end
        endcase
    always @(posedge clk or negedge rst_n)
        if(!rst_n) STATE <= 2'b00:
        else STATE <= next_STATE;
endmodule

 自动售报机

module auto_sellor(current_state, data_out,
        data_out_return1, data_out_return2, clk,
        rst_n, data_in);
    parameter state_width = 3, data_in_width = 3;
    output [state_width-1:0] current_state;
    output data_out, data_out_return1,
        data_out_return2;
    input [dala_in_width-1:O] data_in;
    input clk, rst_n;
    reg [state_width-l:OJ current_state, next_state;
    reg data_out, data_out_returnl, data_out_return2;
    always @(current_state or data_in)
    case (current_state)
        3'b000: case (data_in)
            3'b000: begin
                        next_state <= 3'b000;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b001: begin
                        next_state <= 3'b001;
                        data_out <= 1'bO;
                        data_out_return 1 <= 1'bO;
                        data_out_retum2 <= 1'bO;
                    end
            3'b010: begin
                        next_state <= 3'b010;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b011: begin
                        next_state <= 3'bl01;
                        data_out <= 1'bO;
                        data_out_return 1 <= 1'bO;
                        data_out_retum2 <= 1'bO;
                    end
            3'bl00: begin
                        next_state <= 3'bOOO;
                        data_out <= 1'bl;
                        data_out_retum1 <= 1'bO;
                        data_out_retum2 <= 1'bl;
                    end
            endcase
        3'b001: case (data_in)
            3'b000: begin
                        next_state <= 3'b001;
                        data_out <= 1'b0;
                        data_out_retum1 <= 1'b0;
                        data_out_retum2 <= 1'b0;
                    end
            3'b001: begin
                        next_state <= 3'b010;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0:
                        data_out_return2 <= 1'b0;
                    end
            3'b010: begin
                        nexl_state <= 3'b011;
                        data_out <= 1'b0;
                        data_oul_return1 <= 1'b0;
                        data_out_return2 <= 1'b0:
                    end
            3'b011: begin
                        next_state <= 3'b110;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0:
                    end
            endcase
        3'b010: case (daia_in)
            3'b000: begin
                        next_state <= 3'b010;
                        data_out <= 1'b0;
                        data_out_returnl <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'bOO1: begin
                        next_state <= 3'b011;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_oul_return2 <= 1'b0;
                    end
            3'b010: begin
                        next_state <= 3'b100;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b011: begin
                        next_state <= 3'b111;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            endcase
        3'bO11: case (data_in)
            3'b000: begin
                        next_state <= 3'b011;
                        data_out <= 1'b0;
                        data_out_retuml <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b001: begin
                        next_state <= 3'b100;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b010: begin
                        next_state <= 3'b101;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b011: begin
                        next_state <= 3'b000;
                        data_out <= 1'b1;
                        data_out_returnl <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            endcase
        3'blOO: case (data_in)
            3'bOOO: begin
                        next_state <= 3'b000;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            31)001: begin
                        next_state <= 3'b101;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b010: begin
                        next_state <= 3'b110;
                        data_out <= 1'b0;
                        data_oul_return1 <= 1'b0;
                        data_out_retumrn2 <= 1'b0;
                    end
            3'b011: begin
                        next_state <= 3'b000;
                        data_out <= 1'b1;
                        data_out_return1 <= 1'b1;
                        data_out_return2 <= 1'b0;
                    end
        endcase
        3'b101: case (data_in)
            3'bOOO: begin
                        next_state <= 3'b101;
                        data_out <= 1'b0;
                        data_out_retuml <= 1'b0;
                        data_out_retum2 <= 1'b0;
                    end
            3'bOO1: begin
                        next_state <= 3'b110;
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
            3'b010: begin
                        next_state v= 3'bl 11;
                        data_out <= 1'bO;
                        data_out_retum1 <= 1'bO;
                        data_out_retum2 <= 1'bO;
                    end
            3'bO11: begin
                        next_state <= 3'b000;
                        data_out <= 1'b1;
                        data_out_return1 <= 1'b0;
                        data_out_return2 <= 1'b1;
                    end
        endcase
        3'b110: case (data_in)
            3'b000: begin
                        next_state <= 3'b110:
                        data_out <= 1'b0;
                        data_out_return1 <= 1'b0;
                        data_out_relurn2 <= 1'b0:
                    end
            3'b001: begin
                        next_state <= 3'b111;
                        data_out <= 1'b0;
                        data_out_relurnl <= 1'bO:
                        data_out_return2 <= 1'bO;
                    end
            3'b010: begin
                        next_state <= 3'bOOO;
                        data_out <= 1'b1;
                        data_out_return1 <= 1'bO;
                        data_out_return2 <= 1'bO;
                    end
        endcase
        3'b111: case (data_in)
            3'bOOO: begin
                        next_state <= 3'b111;
                        data_out <= 1'b0;
                        data_oul_return 1 <= 1'b0;
                        data_out_retum2 <= 1'b0;
                    end
            3'bOO1: begin
                        next_state <= 3'b000;
                        data_out <= 1'b1;
                        data_out_retum 1 <= 1'b0;
                        data_out_return2 <= 1'b0;
                    end
        endcase
    endcase
    always @(posedge clk or rst_n)
    if(!rst_n)
        current_state <= 3'bOOO;
    else
        current_state <= next_state;
endmodule

“11010”序列检测器

module seqdet (D_out, D_in, rst_n, clk);
    parameter IDLE = 3'd0, A = 3'd1,B = 3'd2, C = 3'd3, D = 3'd4, E = 3'd5;
    output D_out;
    input D_in, rst_n, clk;
    reg [2:0] state, next_state;
    wire D_out;
        assign D_out = (state == E)? 1:0;
        always @(state or D_in)
            case (state)
                IDLE : if(D_in) next_state = A;
                        else next_state = IDLE;
                A : if(D_in) next_state = B;
                    else next_state = IDLE;
                B : if(D_in) next_state = B;
                    else next_state = C;
                C : if (D_in) next_state = D;
                    else next_state = IDLE;
                D : if (D_in) next_state = B;
                    else next_state = E;
                E : if (D_in) next_state = IDLE;
                    else next_state = A;
                default: next_state = IDLE;
            endcase
        always @(posedge clk)
            state <= next_state;
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值