📄 i2c_control_blk_ver.v
字号:
`state_type_WAIT_ACK : // ----------- WAIT_ACK 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)) visual_0_state <= `state_type_XMIT_DATA; else begin // no ack received, generate a stop and return // to IDLE state if (master_slave) visual_0_sm_stop <= 1'b1; visual_0_state <= `state_type_IDLE; end endcase end // ************************ START/STOP Detect Process ************************ // This process detects the start and stop conditions. // by using SDA as a clock. always @( negedge (sda) or negedge (reset)) begin if (!reset) visual_0_detect_start <= 1'b0; else if (scl) visual_0_detect_start <= 1'b1; else if (state == `state_type_HEADER) visual_0_detect_start <= 1'b0; else visual_0_detect_start <= 1'b0; end // RXAK - Received Acknowledge // RXAK contains the value of SDA during the acknowledge bit of a bus cycle. If =0, then // an acknowledge signal has been received, if 1, then no acknowledge has been received. // This bit is not cleared at reset. The CPLD will reset this bit upon power-up always @( negedge (scl) ) begin begin begin if (state == `state_type_ACK_HEADER || state == `state_type_ACK_DATA || state == `state_type_WAIT_ACK) visual_0_rxak <= sda_in; end end end always @( posedge (sda) or negedge (reset)) begin if (!reset) visual_0_detect_stop <= 1'b0; else if (scl) visual_0_detect_stop <= 1'b1; else if (detect_start) visual_0_detect_stop <= 1'b0; else visual_0_detect_stop <= 1'b0; end always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) visual_0_i2c_header_en <= 1'b0; else if ((detect_start) || (state == `state_type_HEADER)) visual_0_i2c_header_en <= 1'b1; else visual_0_i2c_header_en <= 1'b0; end // ************************ Bus Busy Process ************************ // This process detects the start and stop conditions and sets the bus busy bit // It also describes a delayed version of the bus busy bit which is used to determine // MAL. MAL should be set if a start is detected while the bus is busy, however, the code below // sets bus_busy as soon as START is detected which would always set MAL. Therefore, a delayed // version of bus_busy is generated and used to determine MAL. always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) begin visual_0_bus_busy <= 1'b0; visual_0_bus_busy_d1 <= 1'b0; end else begin visual_0_bus_busy_d1 <= bus_busy; if (detect_start) visual_0_bus_busy <= 1'b1; if (detect_stop) visual_0_bus_busy <= 1'b0; end end // set SDA and SCL assign sda = (sda_oe == 1'b1 ? 1'b0 : 1'bz); assign scl = (scl_out_reg == 1'b0 ? 1'b0 : 1'bz); assign scl_not = (~ (scl)) ; // sda_oe is set when master and arbitration is not lost and data to be output = 0 or // when slave and data to be output is 0 assign sda_oe = (((master_slave == 1'b1 && arb_lost == 1'b0 && sda_out_reg == 1'b0) || (master_slave == 1'b0 && slave_sda == 1'b0) || stop_scl_reg == 1'b1) ? 1'b1 : 1'b0); // the following signals are only here because Viewlogic's VHDL compiler won't allow a constant // to be used in a component instantiation assign reg_clr = `CLR_REG; assign zero_sig = ZERO; assign cnt_zero = `ZERO_CNT; assign cnt_start = `START_CNT; assign rep_start = rsta; // repeat start signal is RSTA control bit // MBB - Bus Busy Bit // This bit indicates the status of the bus. This bit is set when a START signal is detected and // cleared when a stop signal is detected. It is also cleared on reset. This bit is identical to // the signal bus_busy set in the process set_bus_busy. assign mbb = bus_busy; // ************************ uP Address Register ************************ assign addr_match = (i2c_header[7:1] == madr[7:1] ? 1'b1 : 1'b0); assign i2c_header_ld = 1'b0; // Counter control lines assign bit_cnt_en = ((state == `state_type_HEADER) || (state == `state_type_RCV_DATA) || (state == `state_type_XMIT_DATA) ? 1'b1 : 1'b0); assign bit_cnt_ld = ((state == `state_type_IDLE) || (state == `state_type_ACK_HEADER) || (state == `state_type_ACK_DATA) || (state == `state_type_WAIT_ACK) ? 1'b1 : 1'b0); // MAL - Arbitration Lost Bit // This bit is set when the arbitration procedure is lost. Arbitration is lost when: // 1. SDA is sampled low when the master drives high during addr or data transmit cycle // 2. SDA is sampled low when the master drives high during the acknowledge bit of a // data receive cycle // 3. A start cycle is attempted when the bus is busy // 4. A repeated start is requested in slave mode // 5. A stop condition is detected that the master did not request it. // This bit is cleared upon reset and when the software writes a '0' to it // Conditions 1 & 2 above simply result in SDA_IN not matching SDA_OUT while SCL is high. This // design will not generate a START condition while the bus is busy. When a START is detected, this hardware // will set the bus busy bit and gen_start stays set until detect_start asserts, therefore will have // to compare with a delayed version of bus_busy. Condition 3 is really just // a check on the uP software control registers as is condition 4. Condition 5 is also taken care // of by the fact that SDA_IN does not equal SDA_OUT, however, this process also tests for if a stop // condition has been detected when this master did not generate it always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) visual_0_mal <= 1'b0; else begin if (mal_bit_reset) visual_0_mal <= 1'b0; else if (master_slave) begin if ((arb_lost) || (bus_busy_d1 && gen_start) || (detect_stop && ! gen_stop && !sm_stop)) visual_0_mal <= 1'b1; end else if (rsta) // repeated start requested while slave visual_0_mal <= 1'b1; end end // MAAS - Addressed As Slave Bit // When its own specific address (MADR) matches the I2C Address, this bit is set. The CPU is // interrupted provided the MIEN is set. Then the CPU needs to check the SRW bit and set its // TX-RX mode accordingly. Writing to the MBCR clears this bit always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) visual_0_maas <= 1'b0; else if (mbcr_wr) visual_0_maas <= 1'b0; else if (state == `state_type_ACK_HEADER) visual_0_maas <= addr_match; // the signal address match compares MADR with I2_ADDR else visual_0_maas <= maas; end // ************************ uP Status Register Bits Processes ************************ // The following processes and assignments set the bits of the MBUS status register MBSR // // MCF - Data transferring bit // While one byte of data is being transferred, this bit is cleared. It is set by the falling edge // of the 9th clock of a byte transfer and is not cleared at reset always @( negedge (scl) or negedge (reset) ) begin if (!reset) visual_0_mcf <= 1'b0; else if (bit_cnt == `CNT_DONE) visual_0_mcf <= 1'b1; else visual_0_mcf <= 1'b0; end // SRW - Slave Read/Write Bit // When MAAS is set, SRW indicates the value of the R/W command bit of the calling address sent // from the master. This bit is only valid when a complete transfer has occurred and no other // transfers have been initiated. The CPU uses this bit to set the slave transmit/receive mode. // This bit is reset by reset always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) visual_0_srw <= 1'b0; else if (state == `state_type_ACK_HEADER) visual_0_srw <= i2c_header[0]; else visual_0_srw <= srw; end always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) begin visual_0_shift_reg_en <= 1'b0; visual_0_shift_reg_ld <= 1'b0; end else begin if (((master_slave && state == `state_type_HEADER) || (state == `state_type_RCV_DATA) || (state == `state_type_XMIT_DATA))) visual_0_shift_reg_en <= 1'b1; else visual_0_shift_reg_en <= 1'b0; if (((master_slave && state == `state_type_IDLE) || (state == `state_type_WAIT_ACK) || (state == `state_type_ACK_HEADER && i2c_header[0] && !master_slave) || (state == `state_type_ACK_HEADER && mtx && master_slave))) visual_0_shift_reg_ld <= 1'b1; else visual_0_shift_reg_ld <= 1'b0; end end // MIF - M-bus Interrupt // The MIF bit is set when an interrupt is pending, which causes a processor interrupt // request provided MIEN is set. MIF is set when: // 1. Byte transfer is complete (set at the falling edge of the 9th clock // 2. MAAS is set when in slave receive mode // 3. Arbitration is lost // This bit is cleared by reset and software writting a '0'to it always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) visual_0_mif <= 1'b0; else begin if (mif_bit_reset) visual_0_mif <= 1'b0; else if (mal || mcf || (maas && !i2c_header[0] && !master_slave)) visual_0_mif <= 1'b1; end end // ************************ Slave and Master SDA ************************ always @( negedge (reset) or posedge (sys_clk) ) begin if (!reset) begin visual_0_master_sda <= 1'b1; visual_0_slave_sda <= 1'b1; end else begin if (state == `state_type_HEADER || state == `state_type_XMIT_DATA) visual_0_master_sda <= shift_out; else if (state == `state_type_ACK_DATA) visual_0_master_sda <= txak; else visual_0_master_sda <= 1'b1; // For the slave SDA, address match (MAAS) only has to be checked when // state is ACK_HEADER because state // machine will never get to state XMIT_DATA or ACK_DATA // unless address match is a one. if ((maas && state == `state_type_ACK_HEADER) || (state == `state_type_ACK_DATA)) visual_0_slave_sda <= txak; else if ((state == `state_type_XMIT_DATA)) visual_0_slave_sda <= shift_out; else visual_0_slave_sda <= 1'b1; end end // ************************ uP Data Register ************************ // Register for uP interface MBDR_I2C always @( posedge (sys_clk) or negedge (reset) ) begin if (!reset) visual_0_mbdr_i2c <= {{8{ 1'b0 }}}; else if ((state == `state_type_ACK_DATA) || (state == `state_type_WAIT_ACK)) visual_0_mbdr_i2c <= shift_reg; else visual_0_mbdr_i2c <= mbdr_i2c; end endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -