📄 pci_spoci_ctrl.v
字号:
if (clk_gen_cnt == 'h0) begin scl_oe = 1'b1 ; scl_oe_en = 1'b1 ; end // after half of clock low time, disable the sda driver if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; end // after clock low time, disable the scl driver - generate low to high transition on the scl line if (clk_gen_cnt == (period_cnt >> 1)) begin scl_oe = 1'b0 ; scl_oe_en = 1'b1 ; end // after 1/2 clock high time, report ack or nack condition, depending on the sda input state if (clk_gen_cnt == ((period_cnt >> 1) + (period_cnt >> 2)) ) begin ack_rec = ~sda_i_reg ; nack_rec = sda_i_reg ; end // after clock period time expires, check what to do next if (clk_gen_cnt == period_cnt) begin clk_gen_cnt_clr = 1'b1 ; if (send_bit) tx_rx_next_state = tx_rx_send_bits ; else if (rec_bit) tx_rx_next_state = tx_rx_rec_bits ; else if (send_stop) tx_rx_next_state = tx_rx_stop ; else if (send_start) tx_rx_next_state = tx_rx_restart ; else begin // this should never happen tx_rx_next_state = tx_rx_idle ; end end end tx_rx_send_nack: begin clk_gen_cnt_en = 1'b1 ; // generate high to low transition on the scl line if (clk_gen_cnt == 'h0) begin scl_oe = 1'b1 ; scl_oe_en = 1'b1 ; end // after half of clock low time, disable the sda driver if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; nack_sent = 1'b1 ; end // after clock low time, disable the scl driver - generate low to high transition on the scl line if (clk_gen_cnt == (period_cnt >> 1)) begin scl_oe = 1'b0 ; scl_oe_en = 1'b1 ; end // after clock period time expires, check what to do next if (clk_gen_cnt == period_cnt) begin clk_gen_cnt_clr = 1'b1 ; // after the no acknowledge is sent, the only possible next state is stop // state if (send_stop) tx_rx_next_state = tx_rx_stop ; else begin // this should never happen tx_rx_next_state = tx_rx_idle ; end end end tx_rx_restart: begin clk_gen_cnt_en = 1'b1 ; // generate high to low transition if (clk_gen_cnt == 'h0) begin scl_oe = 1'b1 ; scl_oe_en = 1'b1 ; end // after half of clock low time, release sda line if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; end // generate low to high transition if (clk_gen_cnt == (period_cnt >> 1)) begin clk_gen_cnt_clr = 1'b1 ; scl_oe = 1'b0 ; scl_oe_en = 1'b1 ; if (send_start) tx_rx_next_state = tx_rx_start ; else tx_rx_next_state = tx_rx_idle ; end end tx_rx_stop: begin clk_gen_cnt_en = 1'b1 ; // generate high to low transition if (clk_gen_cnt == 'h0) begin scl_oe = 1'b1 ; scl_oe_en = 1'b1 ; end // after half of clock low time, drive sda line low if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = 1'b1 ; sda_oe_en = 1'b1 ; end // generate low to high transition if (clk_gen_cnt == (period_cnt >> 1)) begin scl_oe = 1'b0 ; scl_oe_en = 1'b1 ; end // after full clock period, release the sda line if (clk_gen_cnt == period_cnt) begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; stop_sent = 1'b1 ; tx_rx_next_state = tx_rx_idle ; end end endcaseendreg [rw_seq_state_width - 1:0] rw_seq_state ;reg doing_read , doing_write , doing_seq_read , adr_set ;reg [ 3: 0] bits_transfered ;always@(posedge clk_i or posedge reset_i)begin if (reset_i) begin rw_seq_state <= rw_seq_idle ; adr_set <= 1'b0 ; doing_read <= 1'b0 ; doing_write <= 1'b0 ; doing_seq_read <= 1'b0 ; dat_o <= 'h0 ; tx_shift_reg <= 'h0 ; send_start <= 'h0 ; send_stop <= 'h0 ; send_bit <= 'h0 ; send_nack <= 'h0 ; rec_ack <= 'h0 ; no_ack_o <= 'h0 ; bits_transfered <= 'h0 ; write_done_o <= 'h0 ; dat_rdy_o <= 'h0 ; send_ack <= 'h0 ; rec_bit <= 'h0 ; end else begin case (rw_seq_state) rw_seq_idle: begin tx_shift_reg <= {4'b1010, adr_i[10: 8], 1'b0} ; adr_set <= 1'b0 ; if ( tx_rx_sm_idle & ~(doing_write | doing_read | doing_seq_read) ) begin if (do_write_i | do_rnd_read_i | do_seq_read_i) begin rw_seq_state <= rw_seq_tx_ctrl ; send_start <= 1'b1 ; end if (do_write_i) doing_write <= 1'b1 ; else if (do_rnd_read_i) doing_read <= 1'b1 ; else if (do_seq_read_i) doing_seq_read <= 1'b1 ; end else begin doing_write <= 1'b0 ; doing_read <= 1'b0 ; doing_seq_read <= 1'b0 ; end end rw_seq_tx_ctrl: begin if (send_start) begin bits_transfered <= 'h0 ; if (start_sent) begin send_start <= 1'b0 ; send_bit <= 1'b1 ; end end else if (send_bit) begin if (bit_sent) begin bits_transfered <= bits_transfered + 1'b1 ; tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ; end if (bits_transfered == 'h8) begin send_bit <= 1'b0 ; rec_ack <= 1'b1 ; end end else if (rec_ack) begin bits_transfered <= 'h0 ; if (ack_rec | nack_rec) rec_ack <= 1'b0 ; if (ack_rec) begin if (doing_write | ~adr_set) begin rw_seq_state <= rw_seq_tx_adr ; tx_shift_reg <= adr_i[ 7: 0] ; send_bit <= 1'b1 ; end else begin rw_seq_state <= rw_seq_rx_byte ; rec_bit <= 1'b1 ; end end else if (nack_rec) begin no_ack_o <= 1'b1 ; send_stop <= 1'b1 ; end end else if (send_stop) begin no_ack_o <= 1'b0 ; if (stop_sent) begin send_stop <= 1'b0 ; rw_seq_state <= rw_seq_idle ; end end end rw_seq_tx_adr: begin if (send_bit) begin if (bit_sent) begin bits_transfered <= bits_transfered + 1'b1 ; tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ; end if (bits_transfered == 'h8) begin send_bit <= 1'b0 ; rec_ack <= 1'b1 ; end end else if (rec_ack) begin bits_transfered <= 'h0 ; if (ack_rec | nack_rec) rec_ack <= 1'b0 ; if (ack_rec) begin adr_set <= 1'b1 ; if (doing_write) begin send_bit <= 1'b1 ; rw_seq_state <= rw_seq_tx_byte ; tx_shift_reg <= dat_i ; end else if (doing_read | doing_seq_read) begin send_start <= 1'b1 ; rw_seq_state <= rw_seq_tx_ctrl ; tx_shift_reg <= 8'b10100001 ; end end else if (nack_rec) begin no_ack_o <= 1'b1 ; send_stop <= 1'b1 ; end end else if (send_stop) begin no_ack_o <= 1'b0 ; if (stop_sent) begin send_stop <= 1'b0 ; rw_seq_state <= rw_seq_idle ; end end end rw_seq_tx_byte: begin if (send_bit) begin if (bit_sent) begin bits_transfered <= bits_transfered + 1'b1 ; tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ; end if (bits_transfered == 'h8) begin send_bit <= 1'b0 ; rec_ack <= 1'b1 ; end end else if (rec_ack) begin bits_transfered <= 'h0 ; if (ack_rec | nack_rec) begin rec_ack <= 1'b0 ; send_stop <= 1'b1 ; end if (nack_rec) no_ack_o <= 1'b1 ; if (ack_rec) write_done_o <= 1'b1 ; end else if (send_stop) begin no_ack_o <= 1'b0 ; write_done_o <= 1'b0 ; if (stop_sent) begin send_stop <= 1'b0 ; rw_seq_state <= rw_seq_idle ; end end end rw_seq_rx_byte: begin if (rec_bit) begin if (bit_rec) begin bits_transfered <= bits_transfered + 1'b1 ; dat_o <= {dat_o[6:0], sda_i_reg} ; end if (bits_transfered == 'h8) begin rec_bit <= 1'b0 ; dat_rdy_o <= 1'b1 ; if (doing_read) send_nack <= 1'b1 ; else send_ack <= 1'b1 ; end end else if (send_nack) begin dat_rdy_o <= 1'b0 ; bits_transfered <= 'h0 ; if (nack_sent) begin send_stop <= 1'b1 ; send_nack <= 1'b0 ; end end else if (send_ack) begin dat_rdy_o <= 1'b0 ; bits_transfered <= 'h0 ; if (~do_seq_read_i) begin send_ack <= 1'b0 ; send_nack <= 1'b1 ; end else if (ack_sent) begin send_ack <= 1'b0 ; rec_bit <= 1'b1 ; end end else if (send_stop) begin if (stop_sent) begin send_stop <= 1'b0 ; rw_seq_state <= rw_seq_idle ; end end end endcase endendendmodule // pci_spoci_ctrl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -