//****边沿检测****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin start_r0 <= 1'b0; start_r1 <= 1'b0; end elsebegin start_r0 <= frame_start; start_r1 <= start_r0; end end
always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin spi_clk_r0 <= CPOL; spi_clk_r1 <= CPOL; end elsebegin spi_clk_r0 <= spi_clk_r; spi_clk_r1 <= spi_clk_r0; end end
//****状态机 状态转换****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin cur_state <= IDLE_S; end elsebegin cur_state <= next_state; end end //********//
//****状态机 次态确定****// always @(*) begin case (cur_state) IDLE_S : begin// 空闲 next_state = (start_posedge)? LOAD_S : IDLE_S; end LOAD_S : begin// 数据装载 next_state = SHIFT_S; end SHIFT_S : begin// 交换数据 next_state = (data_cnt==DATA_WIDTH)? DONE_S : SHIFT_S; end DONE_S : begin// 结束 next_state =IDLE_S; end default : begin next_state = IDLE_S; end endcase end //********//
//****状态机 行为逻辑****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin spi_clk_en <= 1'b0; shift_in_register <= 'd0; shift_out_register <= 'd0; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end elsebegin case (cur_state) IDLE_S : begin spi_clk_en <= 1'b0; shift_in_register <= 'd0; shift_out_register <= 'd0; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end LOAD_S : begin spi_clk_en <= 1'b0; shift_in_register <= 'd0; shift_out_register <= send_data; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end SHIFT_S : begin spi_clk_en <= 1'b1; if (shift_en) begin shift_out_register <= (FIRST_BIT==1)? {shift_out_register[DATA_WIDTH-2:0], 1'd0} : {1'd0, shift_out_register[DATA_WIDTH-1:1]}; end elsebegin shift_out_register <= shift_out_register; end
if (sample_en) begin shift_in_register <= (FIRST_BIT==1)? {shift_in_register[DATA_WIDTH-2:0], miso} : {miso, shift_in_register[DATA_WIDTH-1:1]}; data_cnt <= data_cnt+'d1;
end elsebegin shift_in_register <= shift_in_register; data_cnt <= data_cnt; end
finish_pulse_r <= 1'b0; end DONE_S : begin spi_clk_en <= 1'b0; shift_in_register <= shift_in_register; shift_out_register <= shift_out_register; data_cnt <= 'd0; finish_pulse_r <= 1'b1; end default : begin spi_clk_en <= 1'b0; shift_in_register <= 'd0; shift_out_register <= 'd0; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end endcase end end
//****SPI 时钟生成****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin baud_rate_cnt <= 'd0; end elsebegin if (spi_clk_en) begin if (baud_rate_cnt==BAUD_CNT_THRESHOLD) begin baud_rate_cnt <= 'd0; end elsebegin baud_rate_cnt <= baud_rate_cnt + 'd1; end end elsebegin baud_rate_cnt <= 'd0; end end end
always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin spi_clk_r <= CPOL; end elsebegin if (baud_rate_cnt==BAUD_CNT_THRESHOLD) begin spi_clk_r <= ~spi_clk_r; end elsebegin spi_clk_r <= spi_clk_r; end end end
//****边沿检测****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin spi_clk_r0 <= CPOL; spi_clk_r1 <= CPOL; end elsebegin spi_clk_r0 <= spi_clk; spi_clk_r1 <= spi_clk_r0; end end
always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin cs_n_r0 <= 1'b1; cs_n_r1 <= 1'b1; end elsebegin cs_n_r0 <= cs_n; cs_n_r1 <= cs_n_r0; end end
//****状态机 状态转换****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin cur_state <= IDLE_S; end elsebegin cur_state <= next_state; end end //********//
//****状态机 次态确定****// always @(*) begin case (cur_state) IDLE_S : begin// 空闲 next_state = (cs_n_negedge)? LOAD_S : IDLE_S; end LOAD_S : begin// 数据装载 next_state = SHIFT_S; end SHIFT_S : begin// 交换数据 next_state = (data_cnt==DATA_WIDTH)? DONE_S : SHIFT_S; end DONE_S : begin// 结束 next_state =IDLE_S; end default : begin next_state = IDLE_S; end endcase end //********//
//****状态机 行为逻辑****// always @(posedge sys_clk ornegedge rst_n) begin if (~rst_n) begin shift_in_register <= 'd0; shift_out_register <= 'd0; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end elsebegin case (cur_state) IDLE_S : begin shift_in_register <= 'd0; shift_out_register <= 'd0; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end LOAD_S : begin shift_in_register <= 'd0; shift_out_register <= send_data; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end SHIFT_S : begin if (shift_en) begin shift_out_register <= (FIRST_BIT==1)? {shift_out_register[DATA_WIDTH-2:0], 1'd0} : {1'd0, shift_out_register[DATA_WIDTH-1:1]}; end elsebegin shift_out_register <= shift_out_register; end
if (sample_en) begin shift_in_register <= (FIRST_BIT==1)? {shift_in_register[DATA_WIDTH-2:0], mosi} : {mosi, shift_in_register[DATA_WIDTH-1:1]}; data_cnt <= data_cnt+'d1; end elsebegin shift_in_register <= shift_in_register; data_cnt <= data_cnt; end
finish_pulse_r <= 1'b0; end DONE_S : begin shift_in_register <= shift_in_register; shift_out_register <= shift_out_register; data_cnt <= 'd0; finish_pulse_r <= 1'b1; end default : begin shift_in_register <= 'd0; shift_out_register <= 'd0; data_cnt <= 'd0; finish_pulse_r <= 1'b0; end endcase end end