P1_Verilog-HDL部件及状态机设计

目录:

[toc]

Verilog-HDL语法

  1. 状态编码定义的两种方式:parameter 和 `define 语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //parameter语句
    parameter State1 = 4'b0001, //注意逗号和等号
    State2 = 4'b0010,
    State3 = 4'b0100,
    State4 = 4'b1000; //分号结束

    case (State)
    State1 : begin end
    State2 : begin end

    //`define语句
    `define State1 4'b0000 // 不要加分号和等号
    `define State2 4'b0010
    `define State3 4'b0100
    `define State4 4'b1000

    case (State)
    `State1 : begin end
    `State2 : begin end
    endcase
  2. 同步复位的实现:

    1
    2
    3
    4
    always@(posedge clk) begin
    if (reset == 0) begin end
    else begin /*复位*/ end
    end
  3. 异步复位的实现:

    1
    2
    3
    4
    5
    6
    always@(reset) begin
    if (reset) begin /*复位*/ end
    end
    always@(posedge clk) begin
    if (reset == 0) begin end
    end

状态机编码风格

  1. 一段式状态机:

    一段式状态机将整个状态机编写在一个 always 模块里,该模块采用同步时序逻辑,全部使用非阻塞赋值。该模块既描述状态转移,又描述状态的输入和输出。

  2. 两段式状态机:

    两段式状态机使用两个 always 模块,第一个 always 模块采用同步时序逻辑描述状态转移;第二个 always 模块使用组合逻辑判断状态转移的条件,描述状态转移的规律。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    module fsm_1010 (
    input clk,
    input in,
    output reg out
    );

    reg [2:0] state = 0;
    reg [2:0] next_state;

    // 描述状态转移的时序逻辑
    always @(posedge clk) begin
    state <= next_state; // 这里还可以视情况添加复位功能
    end

    // 判断状态转移条件以及产生输出组合逻辑
    always @(state, in) begin
    case (state)
    0:
    begin
    next_state = ;
    out = ;
    end
    ...
    default: begin end
    endcase
    end

    end module
  3. 三段式状态机:

    三段式状态机使用三个 always 模块,第一个 always 模块采用同步时序逻辑描述状态转移;第二个 always 模块采用组合逻辑判断状态转移条件,描述状态转移规律;第三个 always 模块采用组合逻辑或者时序逻辑述每个状态的输出。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    module fsm_1010 (
    input clk,
    input in,
    output reg out
    );

    reg [2:0] state = 0;
    reg [2:0] next_state;

    // 描述状态转移的时序逻辑
    always @(posedge clk) begin
    state <= next_state;
    end

    // 判断状态转移条件的组合逻辑
    always @(state, in) begin
    case (state)
    0:
    begin
    next_state = ;
    end
    default: begin end
    endcase
    end

    // 产生输出的组合逻辑
    always @(state) begin
    out = ;
    end

    endmodule

和两段式状态机相比,这样可以减少毛刺的产生,这是因为三段式状态机将输出分离成独立的组合逻辑,减小了关键路径和时延。

Verilog-HDL代码规范

  1. 信号名称通常采用 snake_case,即变量名全小写,单词之间用下划线分隔。
  2. 对于复位和使能信号,例如 rstwe,如果添加了 _n 后缀,表示值为0时生效;如果没有添加 _n 后缀,表示值为1时生效。
  3. 通常情况下,一个信号只会在一个 always 块中赋值。
  4. 组合逻辑采用always@(*)块或者assign,组合逻辑的 always 块中所有的赋值请使用阻塞赋值(=)。
  5. 时序逻辑在always@(posedge clk)中实现,时序逻辑 always 块中,所有的赋值请使用非阻塞赋值(<=)。
  6. 除特殊协议,不要使用下降沿触发,不要使用非时钟/复位信号的边沿触发。