📄 pci_spoci_ctrl.v
字号:
////////////////////////////////////////////////////////////////////////// //////// File name: pci_spoci_ctrl //////// //////// This file is part of the "PCI bridge" project //////// http://www.opencores.org/cores/pci/ //////// //////// Author(s): //////// - Miha Dolenc (mihad@opencores.org) //////// //////// ////////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2004 Miha Dolenc, mihad@opencores.org //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer. //////// //////// This source file is free; you can redistribute it //////// and/or modify it under the terms of the GNU Lesser General //////// Public License as published by the Free Software Foundation; //////// either version 2.1 of the License, or (at your option) any //////// later version. //////// //////// This source is distributed in the hope that it will be //////// useful, but WITHOUT ANY WARRANTY; without even the implied //////// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //////// PURPOSE. See the GNU Lesser General Public License for more //////// details. //////// //////// You should have received a copy of the GNU Lesser General //////// Public License along with this source; if not, download it //////// from http://www.opencores.org/lgpl.shtml //////// ////////////////////////////////////////////////////////////////////////////// CVS Revision History//// $Log: pci_spoci_ctrl.v,v $// Revision 1.1 2004/01/24 11:54:18 mihad// Update! SPOCI Implemented!////`include "pci_constants.v"// synopsys translate_off`include "timescale.v"// synopsys translate_onmodule pci_spoci_ctrl( reset_i , clk_i , do_rnd_read_i , do_seq_read_i , do_write_i , write_done_o , dat_rdy_o , no_ack_o , adr_i , dat_i , dat_o , pci_spoci_sda_i , pci_spoci_sda_oe_o , pci_spoci_scl_oe_o);parameter tx_rx_state_width = 9 ;parameter tx_rx_idle = 'h1 ;parameter tx_rx_start = 'h2 ;parameter tx_rx_restart = 'h4 ;parameter tx_rx_send_bits = 'h8 ;parameter tx_rx_rec_bits = 'h10 ;parameter tx_rx_send_ack = 'h20 ;parameter tx_rx_rec_ack = 'h40 ;parameter tx_rx_send_nack = 'h80 ;parameter tx_rx_stop = 'h100 ;parameter rw_seq_state_width = 5 ;parameter rw_seq_idle = 'h1 ;parameter rw_seq_tx_ctrl = 'h2 ;parameter rw_seq_tx_adr = 'h4 ;parameter rw_seq_tx_byte = 'h8 ;parameter rw_seq_rx_byte = 'h10 ;`ifdef PCI33parameter cnt_width = 9 ;parameter period_cnt = 334 ;`endif`ifdef PCI66parameter cnt_width = 10 ;parameter period_cnt = 667 ;`endifinput reset_i , clk_i ;input do_rnd_read_i , do_seq_read_i , do_write_i ;output write_done_o , dat_rdy_o , no_ack_o ;input [10: 0] adr_i ;input [ 7: 0] dat_i ;output [ 7: 0] dat_o ;input pci_spoci_sda_i ;output pci_spoci_sda_oe_o , pci_spoci_scl_oe_o ;reg write_done_o , dat_rdy_o , no_ack_o ;reg [ 7: 0] dat_o ;reg pci_spoci_sda_oe_o , pci_spoci_scl_oe_o ;reg clk_gen_cnt_en ;reg clk_gen_cnt_clr ;reg [cnt_width - 1:0] clk_gen_cnt ;reg [tx_rx_state_width - 1:0] tx_rx_state ;reg [tx_rx_state_width - 1:0] tx_rx_next_state ;reg tx_rx_sm_idle ;reg scl_oe ;reg scl_oe_en ;reg sda_oe ;reg sda_oe_en ;reg sda_i_reg_en ;reg sda_i_reg ;always@(posedge clk_i or posedge reset_i)begin if (reset_i) begin clk_gen_cnt <= 'h0 ; tx_rx_state <= tx_rx_idle ; `ifdef ACTIVE_LOW_OE pci_spoci_sda_oe_o <= 1'b1 ; pci_spoci_scl_oe_o <= 1'b1 ; `endif `ifdef ACTIVE_HIGH_OE pci_spoci_sda_oe_o <= 1'b0 ; pci_spoci_scl_oe_o <= 1'b0 ; `endif sda_i_reg <= 1'b1 ; end else begin tx_rx_state <= tx_rx_next_state ; if (clk_gen_cnt_clr) clk_gen_cnt <= 'h0 ; else if (clk_gen_cnt_en) clk_gen_cnt <= clk_gen_cnt + 1'b1 ; if (sda_oe_en) begin `ifdef ACTIVE_LOW_OE pci_spoci_sda_oe_o <= ~sda_oe ; `endif `ifdef ACTIVE_HIGH_OE pci_spoci_sda_oe_o <= sda_oe ; `endif end if (scl_oe_en) begin `ifdef ACTIVE_LOW_OE pci_spoci_scl_oe_o <= ~scl_oe ; `endif `ifdef ACTIVE_HIGH_OE pci_spoci_scl_oe_o <= scl_oe ; `endif end if (sda_i_reg_en) sda_i_reg <= pci_spoci_sda_i ; endendreg [ 7: 0] tx_shift_reg ;reg send_start ;reg start_sent ;reg send_bit ;reg bit_sent ;reg rec_bit ;reg bit_rec ;reg rec_ack ;reg ack_rec ;reg nack_rec ;reg send_ack ;reg ack_sent ;reg send_nack ;reg nack_sent ;reg send_stop ;reg stop_sent ;always@( tx_rx_state or clk_gen_cnt or send_start or send_bit or tx_shift_reg or send_stop or rec_ack or sda_i_reg or rec_bit or send_ack or send_nack)begin clk_gen_cnt_clr = 1'b0 ; clk_gen_cnt_en = 1'b0 ; tx_rx_next_state = tx_rx_state ; tx_rx_sm_idle = 1'b0 ; scl_oe = 1'b0 ; sda_oe = 1'b0 ; scl_oe_en = 1'b0 ; sda_oe_en = 1'b0 ; start_sent = 1'b0 ; bit_sent = 1'b0 ; ack_rec = 1'b0 ; nack_rec = 1'b0 ; sda_i_reg_en = 1'b0 ; stop_sent = 1'b0 ; bit_rec = 1'b0 ; ack_sent = 1'b0 ; nack_sent = 1'b0 ; case (tx_rx_state) tx_rx_idle: begin tx_rx_sm_idle = 1'b1 ; // from idle state, the only transition can be to the send start bit if (send_start) begin tx_rx_next_state = tx_rx_start ; clk_gen_cnt_clr = 1'b1 ; end end tx_rx_start: begin clk_gen_cnt_en = 1'b1 ; sda_oe = 1'b1 ; // start bit is sent by transmiting 0 on the sda line if (clk_gen_cnt == (period_cnt >> 1)) begin start_sent = 1'b1 ; sda_oe_en = 1'b1 ; end // after half clock period of driving the sda low, the only possible // transition is to send state. // if send bit is not active, stop the procedure - undrive sda if (clk_gen_cnt == period_cnt) begin clk_gen_cnt_clr = 1'b1 ; if (send_bit) begin tx_rx_next_state = tx_rx_send_bits ; end else begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; tx_rx_next_state = tx_rx_idle ; end end end tx_rx_send_bits: begin clk_gen_cnt_en = 1'b1 ; // generate high to low transition on the scl line immediately if (clk_gen_cnt == 'h0) begin scl_oe = 1'b1 ; scl_oe_en = 1'b1 ; end // after half of clock low time, load new value for sda oe, depending on the // msb bit in the shift register if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = ~tx_shift_reg[7] ; sda_oe_en = 1'b1 ; bit_sent = 1'b1 ; end // after clock low time, 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 high time, check what to do next if (clk_gen_cnt == (period_cnt)) begin clk_gen_cnt_clr = 1'b1 ; if (~send_bit) begin // after transmiting all the bits, the only possible transition is to the state // that checks the eprom acknowledge if (rec_ack) tx_rx_next_state = tx_rx_rec_ack ; else begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; tx_rx_next_state = tx_rx_idle ; end end end end tx_rx_rec_bits: begin clk_gen_cnt_en = 1'b1 ; sda_i_reg_en = 1'b1 ; // generate high to low transition on the scl line immediately if (clk_gen_cnt == 'h0) begin scl_oe = 1'b1 ; scl_oe_en = 1'b1 ; end // after half of clock low time, disable sda driver if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; end // after clock low time, 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 half of clock high time, report received bit if (clk_gen_cnt == ((period_cnt >> 1) + (period_cnt >> 2)) ) begin bit_rec = 1'b1 ; end // after clock period is finished, check the next operation if (clk_gen_cnt == (period_cnt)) begin clk_gen_cnt_clr = 1'b1 ; if (~rec_bit) begin // when all bits are received, only nack or ack next states are possible if (send_ack) tx_rx_next_state = tx_rx_send_ack ; else if (send_nack) tx_rx_next_state = tx_rx_send_nack ; else begin tx_rx_next_state = tx_rx_idle ; end end end end tx_rx_send_ack: 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, enable the sda driver if (clk_gen_cnt == (period_cnt >> 2)) begin sda_oe = 1'b1 ; sda_oe_en = 1'b1 ; ack_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 byte is acknowledged, the only possible next state is receive bits // state if (rec_bit) tx_rx_next_state = tx_rx_rec_bits ; else begin // this should never happen sda_oe = 1'b0 ; sda_oe_en = 1'b1 ; tx_rx_next_state = tx_rx_idle ; end end end tx_rx_rec_ack: begin clk_gen_cnt_en = 1'b1 ; sda_i_reg_en = 1'b1 ; // generate high to low transition on the scl line
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -