状态机转换到对信号抽头不可用状态

问题描述 投票:0回答:1

我试图输出一个位在从知道二维数组通过SPI的时间。

logic [7:0] fpga_status_queue [0:17],

我的状态机是出于某种原因要一个奇怪的状态。

18'h

这里是我的代码:

module FPGA_STATUS_READ (
     input clk,
    input sclk, 
    input cs, // Clock Enable
    input rst_n,  // Asynchronous reset active low
    input fpgastatus_command,
    input logic [3:0] group_control,
    input logic [7:0] loopback,
    output logic [7:0] fpga_status_queue [0:17],
    output logic dout
);

    // `include "../../config_files/rtl_config.svh"

    assign fpga_status_queue[ 0] = 8'h1;//{group_control};
    assign fpga_status_queue[ 1] = 8'h1;//{loopback}; 
    assign fpga_status_queue[ 2] = 8'h1;//{synth_version[0]}; 
    assign fpga_status_queue[ 3] = 8'h1;//{synth_version[1]}; 
    assign fpga_status_queue[ 4] = 8'h1;//{synth_version[2]}; 
    assign fpga_status_queue[ 5] = 8'h1;//{grid_version[0]}; 
    assign fpga_status_queue[ 6] = 8'h1;//{grid_version[1]}; 
    assign fpga_status_queue[ 7] = 8'h1;//{grid_version[2]}; 
    assign fpga_status_queue[ 8] = 8'h1;//{pa_version[0]}; 
    assign fpga_status_queue[ 9] = 8'h1;//{pa_version[1]}; 
    assign fpga_status_queue[10] = 8'h1;//{pa_version[2]}; 
    assign fpga_status_queue[11] = 8'h1;//{hdl_version[0]}; 
    assign fpga_status_queue[12] = 8'h1;//{hdl_version[1]}; 
    assign fpga_status_queue[13] = 8'h1;//{hdl_version[2]};     
    assign fpga_status_queue[14] = '1;
    assign fpga_status_queue[15] = '1;
    assign fpga_status_queue[16] = '0;
    assign fpga_status_queue[17] = '0;

    logic bit_run_counter;
    logic bit_load_counter;
    logic [4:0] bit_current_value;
    logic bit_count_reached;

    logic word_run_counter;
    logic word_load_counter;
    logic [4:0] word_current_value;
    logic word_count_reached;

    typedef enum logic [2:0] {IDLE, CS_WAIT, MISO_OUT, BIT_CHANGE, WORD_CHANGE} status_states;
    status_states current_state, next_state;

    always_ff @(posedge clk or negedge rst_n) begin : step_forward
        if(!rst_n)
            current_state                        <= IDLE;
        else 
            current_state                        <= next_state;
    end : step_forward

    always_comb begin : set_next_state
        next_state = IDLE;
        case (current_state)
            IDLE       : next_state = fpgastatus_command ? CS_WAIT : IDLE;
            CS_WAIT    : next_state = ~cs ? MISO_OUT : CS_WAIT;
            MISO_OUT   : begin//next_state = sclk ? bit_count_reached ? word_count_reached ? IDLE: WORD_CHANGE : BIT_CHANGE: MISO_OUT;
                if (sclk && bit_count_reached && word_count_reached) 
                    next_state = IDLE;
                else if (sclk && bit_count_reached) 
                    next_state = WORD_CHANGE;
                else if (sclk)
                    next_state = BIT_CHANGE;
                else 
                    next_state = MISO_OUT;
            end
            BIT_CHANGE : next_state = MISO_OUT;
            WORD_CHANGE: next_state = MISO_OUT;
            default : next_state = IDLE;
        endcase
    end

    always_comb begin : cntr_logic
        bit_run_counter           = '0;
        bit_load_counter          = '0;
        word_run_counter          = '0;
        word_load_counter         = '0;
        dout                      = '0;
        unique case (current_state)
            IDLE       :begin 
                bit_load_counter  = '1;
                word_load_counter = '1;
            end 
            CS_WAIT    :begin 
                bit_load_counter  = '1;
                word_load_counter = '1;
            end 
            MISO_OUT   :begin 
                dout              = fpga_status_queue[word_current_value][bit_current_value];
            end
            BIT_CHANGE :begin 
                bit_run_counter   = '1;
            end 
            WORD_CHANGE:begin 
                word_run_counter  = '1;
                bit_load_counter  = '1;
            end 
            default : dout        = '0;
        endcase
    end

    up_down_counter #(
            .ABSOLUTE_DATA_WIDTH(4)
        ) inst_bit_counter (
            .clk           (clk),
            .run_counter   (bit_run_counter),
            .rst_n         (rst_n),
            .count_value   (5'h7),
            .load_counter  (bit_load_counter),
            .up_counter    ('0),
            .current_value (bit_current_value),
            .count_reached (bit_count_reached)
        );

    up_down_counter #(
            .ABSOLUTE_DATA_WIDTH(5)
        ) inst_word_counter (
            .clk           (clk),
            .run_counter   (word_run_counter),
            .rst_n         (rst_n),
            .count_value   (5'h11),
            .load_counter  (word_load_counter),
            .up_counter    ('0),
            .current_value (word_current_value),
            .count_reached (word_count_reached)
        );

endmodule

它应该去WORD_CHANGE但两者WORD_CHANGEMISO_OUT为当前状态的下一个状态。

Zoomed out image of waves zoomed in image of waves

system-verilog state-machine quartus
1个回答
1
投票

这几乎可以肯定是一个时间问题。我猜,sclk不同步到clk - 也许它直接连接到设备输入引脚。

问题是这样的一段代码:

(...)
else if (sclk)
   next_state = BIT_CHANGE;
else 
   next_state = MISO_OUT;

每当sclk转换从零到一,逻辑将提高相应于所述next_state BIT_CHANGE比特,并且在平行降低对应于next_stateMISO_OUT位。如发生这种情况,可以存在一个短暂的瞬间,其中两个位都被设定或没有位被设置,这取决于逻辑更快。如果你运气不好,并有在这个确切的时刻提升clk,你将进入你所观察的情况,即状态机似乎是两个国家在同一时间。

解决的办法是同步sclkcs,并且确定下一个状态的任何其它信号clk。这样的同步通常是通过简单地通过两个触发器发送的信号来完成。

© www.soinside.com 2019 - 2024. All rights reserved.