📄 i2c_control_blk_ver.v
字号:
visual_0_arb_lost <= 1'b1; visual_0_msta_rst <= 1'b1; end else begin visual_0_arb_lost <= arb_lost; visual_0_msta_rst <= 1'b0; end end end // ************************ SCL_Generator Process ************************ // This process generates SCL and SDA when in Master mode. It generates the START // and STOP conditions. If arbitration is lost, SCL will be generated until the // end of the byte transfer. always @(scl_state or arb_lost or sm_stop or gen_stop or rep_start or bus_busy or gen_start or master_slave or stop_scl_reg or clk_cnt or bit_cnt or scl_in or state or sda_out or sda_out_reg or stop_scl_reg or master_sda) begin // state machine defaults visual_0_scl_out <= 1'b1; visual_0_sda_out <= sda_out_reg; visual_0_stop_scl <= stop_scl_reg; visual_0_clk_cnt_en <= 1'b0; visual_0_clk_cnt_rst <= 1'b1; visual_0_next_scl_state <= scl_state; case (scl_state) `scl_state_type_SCL_IDLE : begin visual_0_sda_out <= 1'b1; visual_0_stop_scl <= 1'b0; // leave IDLE state when master, bus is idle, and gen_start if (master_slave && !bus_busy && gen_start) visual_0_next_scl_state <= `scl_state_type_START; end `scl_state_type_START : begin // generate start condition visual_0_clk_cnt_en <= 1'b1; visual_0_clk_cnt_rst <= 1'b0; visual_0_sda_out <= 1'b0; visual_0_stop_scl <= 1'b0; if (clk_cnt == `START_HOLD) visual_0_next_scl_state <= `scl_state_type_SCL_LOW_EDGE; else visual_0_next_scl_state <= `scl_state_type_START; end `scl_state_type_SCL_LOW_EDGE : begin visual_0_clk_cnt_rst <= 1'b1; visual_0_scl_out <= 1'b0; visual_0_next_scl_state <= `scl_state_type_SCL_LOW; visual_0_stop_scl <= 1'b0; end `scl_state_type_SCL_LOW : begin visual_0_clk_cnt_en <= 1'b1; visual_0_clk_cnt_rst <= 1'b0; visual_0_scl_out <= 1'b0; // set SDA_OUT based on control signals if (arb_lost) visual_0_stop_scl <= 1'b0; else if (((sm_stop || gen_stop) && (state != `state_type_ACK_DATA && state != `state_type_ACK_HEADER && state != `state_type_WAIT_ACK))) begin visual_0_sda_out <= 1'b0; visual_0_stop_scl <= 1'b1; end else if (rep_start) begin visual_0_sda_out <= 1'b1; visual_0_stop_scl <= 1'b0; end else if (clk_cnt == `DATA_HOLD) begin visual_0_sda_out <= master_sda; visual_0_stop_scl <= 1'b0; end else visual_0_stop_scl <= 1'b0; // determine next state if (clk_cnt == `LOW_CNT) if (bit_cnt == `CNT_DONE && arb_lost) visual_0_next_scl_state <= `scl_state_type_SCL_IDLE; else visual_0_next_scl_state <= `scl_state_type_SCL_HIGH_EDGE; else visual_0_next_scl_state <= `scl_state_type_SCL_LOW; end `scl_state_type_SCL_HIGH_EDGE : begin visual_0_clk_cnt_rst <= 1'b1; visual_0_scl_out <= 1'b1; if (((sm_stop || gen_stop) && (state != `state_type_ACK_DATA && state != `state_type_ACK_HEADER && state != `state_type_WAIT_ACK))) visual_0_stop_scl <= 1'b1; else visual_0_stop_scl <= 1'b0; // this state sets SCL high // stay in this state until SCL_IN = 1 // this will hold the counter in reset until all SCL drivers // have released SCL to 1 if (!scl_in) visual_0_next_scl_state <= `scl_state_type_SCL_HIGH_EDGE; else visual_0_next_scl_state <= `scl_state_type_SCL_HIGH; end `scl_state_type_SCL_HIGH : begin // now all SCL drivers have set SCL to '1' // begin count for high time visual_0_clk_cnt_en <= 1'b1; visual_0_clk_cnt_rst <= 1'b0; visual_0_scl_out <= 1'b1; // check to see if a repeated start or a stop needs to be // generated. If so, only hold SCL high for half of the high time if (clk_cnt == `HIGH_CNT_2) begin begin if (rep_start) visual_0_next_scl_state <= `scl_state_type_START; else if (stop_scl_reg) visual_0_next_scl_state <= `scl_state_type_SCL_IDLE; end end else if (clk_cnt == `HIGH_CNT) visual_0_next_scl_state <= `scl_state_type_SCL_LOW_EDGE; else visual_0_next_scl_state <= `scl_state_type_SCL_HIGH; end endcase end always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) begin visual_0_scl_state <= `scl_state_type_SCL_IDLE; visual_0_sda_out_reg <= 1'b1; visual_0_scl_out_reg <= 1'b1; visual_0_stop_scl_reg <= 1'b0; end else begin visual_0_scl_state <= next_scl_state; visual_0_sda_out_reg <= sda_out; visual_0_scl_out_reg <= scl_out; visual_0_stop_scl_reg <= stop_scl; end end // ************************ Input Registers Process ************************ // This process samples the incoming SDA and SCL with the system clock always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) begin visual_0_sda_in <= 1'b1; visual_0_scl_in <= 1'b1; visual_0_msta_d1 <= 1'b0; visual_0_sda_out_reg_d1 <= 1'b1; end else begin // the following if, then, else clauses are used // because scl may equal 'H' or '1' if (!scl) visual_0_scl_in <= 1'b0; else visual_0_scl_in <= 1'b1; if (!sda) visual_0_sda_in <= 1'b0; else visual_0_sda_in <= 1'b1; visual_0_sda_out_reg_d1 <= sda_out_reg; visual_0_msta_d1 <= msta; end end // ************************ uP Control Bits Process ************************ // This process detects the rising and falling edges of MSTA and sets signals to // control generation of start and stop conditions // This process also sets the master slave bit based on MSTA if and only if it is not // in the middle of a cycle, i.e. bus_busy = '0' always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) begin visual_0_gen_start <= 1'b0; visual_0_gen_stop <= 1'b0; visual_0_master_slave <= 1'b0; end else begin if (!msta_d1 && msta) // rising edge of MSTA - generate start condition visual_0_gen_start <= 1'b1; else if (detect_start) visual_0_gen_start <= 1'b0; if (!arb_lost && msta_d1 && !msta) // falling edge of MSTA - generate stop condition only // if arbitration has not been lost visual_0_gen_stop <= 1'b1; else if (detect_stop) visual_0_gen_stop <= 1'b0; if (!bus_busy) visual_0_master_slave <= msta; else visual_0_master_slave <= master_slave; end end // ************************ Main State Machine Process ************************ // The following process contains the main I2C state machine for both master and slave // modes. This state machine is clocked on the falling edge of SCL. DETECT_STOP must stay as // an asynchronous reset because once STOP has been generated, SCL clock stops. always @( negedge (scl) or negedge (reset)) begin if (!reset) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end else case (state) `state_type_IDLE : // ----------- IDLE STATE ------------- if (detect_start) visual_0_state <= `state_type_HEADER; else if (detect_stop) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end `state_type_HEADER : // ----------- HEADER STATE ------------- if (bit_cnt == `CNT_DONE) visual_0_state <= `state_type_ACK_HEADER; else if (detect_stop) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end `state_type_ACK_HEADER : // ----------- ACK_HEADER STATE ------------- if (arb_lost) visual_0_state <= `state_type_IDLE; else if (detect_stop) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end else if (!sda_in) // ack has been received, check for master/slave if (master_slave) // master, so check mtx bit for direction if (!mtx) // receive mode visual_0_state <= `state_type_RCV_DATA; else // transmit mode visual_0_state <= `state_type_XMIT_DATA; else if (addr_match) // if maas = '1' then // addressed slave, so check I2C_HEADER(0) for direction if (!i2c_header[0]) // receive mode visual_0_state <= `state_type_RCV_DATA; else // transmit mode visual_0_state <= `state_type_XMIT_DATA; else // not addressed, go back to IDLE visual_0_state <= `state_type_IDLE; else begin // no ack received, stop visual_0_state <= `state_type_IDLE; if (master_slave) visual_0_sm_stop <= 1'b1; end `state_type_RCV_DATA : // ----------- RCV_DATA State -------------- // If stop signal detected // if (detect_stop = '1') then // state <= IDLE; // Continue transmitting if (bit_cnt == `CNT_DONE) // Send an acknowledge visual_0_state <= `state_type_ACK_DATA; else if (detect_stop) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end `state_type_XMIT_DATA : // ---------- XMIT_DATA State -------------- // If stop signal detected // if (detect_stop = '1') then // state <= IDLE; if (bit_cnt == `CNT_DONE) // Wait for acknowledge visual_0_state <= `state_type_WAIT_ACK; else if (detect_stop) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end `state_type_ACK_DATA : begin // ----------- ACK_DATA State -------------- visual_0_state <= `state_type_RCV_DATA; if (detect_stop) begin visual_0_state <= `state_type_IDLE; visual_0_sm_stop <= 1'b0; end end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -