Menu Close

Verilog状态机设计与应用

上几节内容讲解了状态机原理,建模以及状态机的分类如Mealy机,Moore机,以及分段描述方法(一段式、二段式、三段式),本节内容主要介绍状态机在程序设计的几个方面的应用。希望通过本章学习,能在以后的程序设计中自觉使用状态机进行建模、程序设计以及解决实际问题的方法。

  1. 序列检测机的设计

序列检测机在通信中应用非常广泛,尤其是在串行通信中,如何在一串连续01序列中找出需要通信帧的帧头,从而使整个数据帧同步起来。简单如UART找出start位,以太网通信中如何找到PREAMBLE和SFD等从而确定一个帧的开始。

例1 :

用状态机设计一个序列检测机,使其可以检测出二进制序列1011,每检测出一组正确的序列,输出一个时钟周期的高电平(脉冲信号)。

序列机的序列图如图1,时序图如图2,

%title插图%num

图1

%title插图%num

图2

根据要求画出状态转移图,如图3

%title插图%num

图3

Verilog 代码如下:

module Squence_Detect
(
    input      rst,
    input      clk,
    input      rx,
    output reg sd_pulse
);
 
localparam  [2:0]   
    S0 = 0,
    S1 = 1,
    S2 = 2,
    S3 = 3,
    S4 = 4;
 
reg        rx_r;
reg  [2:0] cs, ns;
 
always@(posedge clk )   //
    rx_r = rx;
 
always@(posedge clk or posedge rst)
if(rst) 
begin
    cs <= 0;
end
else 
begin
    cs <= ns;
end
 
always@(*)
begin
    ns = cs;
    sd_pulse = 0;
 
    case(cs)
    S0: 
    begin
        if(rx_r)
            ns = S1;
    end
    S1:
    begin
        if(rx_r)
            ns = S1;
        else
            ns = S2;
    end
    S2:
    begin
        if(rx_r)
            ns = S3;
        else
            ns = S0;
    end
    S3:
    begin
        if(rx_r)
            ns = S4;
        else
            ns = S2;
    end
    S4:
    begin
        sd_pulse = 1'b1;
        if(rx_r)
            ns = S1;
        else
            ns = S2;
    end
    default: ns = S0;
    endcase
end
 
endmodule

 

Testbench 程序tb.v

`timescale 1 ns/ 1 ps
 
module tb
(
);
 
parameter  PERIOD = 20;
 
reg  clk;
reg  rst;
reg  tx;
 
wire sd_pulse;
 
initial 
begin
    clk = 0;
    #(PERIOD/2);
 
    forever #(PERIOD/2)  clk = !clk;
end 
 
initial 
begin
    rst = 1'b1;
    #PERIOD 
 
    rst = 1'b0;
end
 
initial 
begin 
    repeat(10) 
    begin
        tx = 0;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b1;
        #PERIOD   tx = 1'b0;
        #PERIOD   tx = 1'b1;
    end
end
 
Squence_Detect    Squence_Detect_inst
(
    .rst      (rst),
    .clk      (clk),
    .rx       (tx),
    .sd_pulse (sd_pulse)
);
 
endmodule

 

Modelsim 的仿真波形图如图4

%title插图%num

图4

2. 线性序列机的生成

线性序列机LSM(Linear sequence machine)可以看作是有限状态机的一种特例,当所描述的状态转移与时钟呈现出一种线性规律时,我们可以直接用时钟计数作为当前状态。在串口收发、非周期波形发生器,电机控制等方面,利用LSM可以更清晰高效的对状态机进行描述和编码。PRBS(Pseudorandom Binary Sequence,伪随机二进制序列)也是由LSM生成的。

例2: 用线性序列机产生一组1010110的二进制序列

线性序列机的时序图如图5

%title插图%num

图5

设计方案:由于使用LSM进行设计,因此我们使用计数器cnt作为状态机的状态,通过对cnt的计数,改变状态机的状态,最终在不同状态下一次输出高低电平,实现特定序列的输出。

首先绘制时序图(图6)和状态转移表(表1):

%title插图%num

图6

表1

%title插图%num

 

Verilog 代码如下:

module lam
(
    input clk,
    input rst,
    output signal
);
 
reg [3:0] cnt = 4'd0;
reg signal = 1'b0;
 
always @(posedge clk)
begin
    if(rst)
        cnt <= 4'd0;
    else
    begin
        if(cnt < 4'd6)
            cnt <= cnt + 1'b1;
        else
            cnt <= 0;
    end
end
 
always @(posedge clk)
begin
    if(rst)
        signal <= 0;
    else
    begin
        case(cnt)
        0: signal <= 1'b1;
        1: signal <= 1'b0;
        2: signal <= 1'b1;
        3: signal <= 1'b0;
        4: signal <= 1'b1;
        5: signal <= signal;
        6: signal <= 1'b0;
        default : signal <= 0;
        endcase
    end
end
 
endmodule

 

上面的程序中,第一段always过程先生成需要的状态,第二段根据状态生成需要的线性机序列。在线性机的描述中有各种各样的应用。最典型的应用是生成需要的已知序列控制特定的设备按照特定的过程运行。第二种是生成伪随机序列,模拟白噪声序列,这种序列在通信的测试中应用非常广泛,在后续通信的理论和实践中会介绍。

练习:

阅读步进电机的资料,设计3相6拍步进电机的序列机。

 

Posted in IC
0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论

相关链接