我正在尝试通过SPI从已知的2D阵列一次输出一位。
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_CHANGE
和MISO_OUT
都应该到达。
答案 0 :(得分:1)
这几乎可以肯定是时间问题。我猜测sclk
与clk
不同步-可能直接连接到设备输入引脚。
问题是这段代码:
(...)
else if (sclk)
next_state = BIT_CHANGE;
else
next_state = MISO_OUT;
每当sclk
从零转换为一时,逻辑将升高对应于next_state
的{{1}}位,并同时降低对应于{{1}的BIT_CHANGE
位}。发生这种情况时,可能会短暂出现两个位都置1或未置位的情况,具体取决于哪种逻辑更快。如果您不走运并且在此刻next_state
上升,那么您将陷入所观察到的状态,其中状态机似乎同时处于两种状态。
解决方案是同步MISO_OUT
,clk
和其他任何确定下一个状态到sclk
的信号。通常通过简单地通过两个触发器发送信号来完成这种同步。