⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 state_machine.v

📁 基于FPGA的PCI接口源代码及Testbenc
💻 V
📖 第 1 页 / 共 2 页
字号:
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Copyright (c) 2001 by Lattice Semiconductor Corporation
// --------------------------------------------------------------------
//
// Permission:
//
//   Lattice Semiconductor grants permission to use this code for use
//   in synthesis for any Lattice programmable logic product.  Other
//   use of this code, including the selling or duplication of any
//   portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL or Verilog source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Lattice Semiconductor provides no warranty
//   regarding the use or functionality of this code.
//
// --------------------------------------------------------------------
//           
//                     Lattice Semiconductor Corporation
//                     5555 NE Moore Court
//                     Hillsboro, OR 97214
//                     U.S.A
//
//                     TEL: 1-800-Lattice (USA and Canada)
//                          408-826-6000 (other locations)
//
//                     web: http://www.latticesemi.com/
//                     email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// Revision History :
// --------------------------------------------------------------------
//   Ver  :| Author            :| Mod. Date :| Changes Made:
//   v1.0 :| D.S.              :| 12/16/98  :| Initial Creation
//   v1.1 :| D.S.              :| 10/05/99  :| added be_oe     
// --------------------------------------------------------------------
//
//	Module  state_machine
//
/*   This module is called state_machine.  It's purpose is to control
  the bus cycle timng of the PCI and bkend Interface signals. 
  The outputs of this block also control output enables for 
  3 state buffers in the design.
 
  The PCI Target State Machine is at the heart of this Reference Design. 
  The State Machine goes from the idle state to one of three possible 
  paths during any given PCI operation.  While in the PCI address phase 
  of a transaction the values on  pci_cbe_l and pci_idsel determine 
  if the transaction is a: Configuration Read or Write, 
  Memory-I/O Read, or a Memory-I/O Write. 

  The designer can modify the state machine HDL code if the 
  functionality of the Back End Device has special system requirements. 
  It may be necessary to implement wait states, or new enable signals 
  for particular applications.  These would require modifications to 
  the HDL code, but embedded HDL comments will guide the designer 
  through the state machine implementation and signal descriptions.

*/

module state_machine (devsel_l, trdy_l, stop_l, pci_ad_oe, 
    dts_oe, par_oe, bk_oe, pci_ad_en, hit_ba0_l, hit_ba1_l, 
    pci_frame_l, pci_idsel, pci_irdy_l, pci_ad, pci_cbe_l, 
    pci_clk, pci_rst_l, abort_sig, data_stop_l, com, 
    data_write_l, ready_l, bkend_abort_l, count_rst_l, count_en_l, 
    retry_l, base_region0_l, base_region1_l, r_w_l, data_read_l,
    be_oe);
 
  output devsel_l; // input to 3 state
  output trdy_l; // input to 3 state
  output stop_l; // input to 3 state
  output pci_ad_oe; // OE for PCI address bus
  output dts_oe; // OE control for the devsel, trdy_l, stop_l (dts)
  output par_oe; // OE control for pci_par
  output bk_oe; // OE control for bkend_dat bus
  output pci_ad_en; // clock enable for the PCI address latch register
  output abort_sig; // sets the status register bit for abort
  output data_write_l; // used as a clock enable for the pci_clk
                       // to the bkend device
  output count_rst_l; // async reset to the retry counter
  output count_en_l; // the clock enable for the retry counter
  output base_region0_l; // chip selects to the backend 
  output base_region1_l; // chip selects to the backend
  output r_w_l; // read == 1 & write == 0
  output data_read_l; // the read strobe for the backend device
  output be_oe; // enables the byte enables for the backend
  input hit_ba0_l; // The pci address is in base address 0
  input hit_ba1_l; // The pci address is in base address 1
  input pci_frame_l; // The pci_frame_l signal
  input pci_idsel; // The pci idsel signal
  input pci_irdy_l; // The pci irdy signal
  input [31:0] pci_ad; // raw pci address data bus
  input [3:0] pci_cbe_l; // The command or byte enables 
  input pci_clk;
  input pci_rst_l;
  input bkend_abort_l; // bkend has had a fatal error
  input data_stop_l; // bkend requesting transaction to stop
  input [1:0] com;
  input ready_l; // bkend is ready to start a transaction cycle
  input retry_l; // when active retry counter has timed out 

  /*********************************************/ 
  /* Some outputs of this block are registered. */
  /* The reg declarations are listed here      */
  /*********************************************/
  
  reg devsel_l; 
  reg trdy_l, stop_l, pci_ad_oe; 
  reg dts_oe, par_oe, bk_oe; 
  reg pci_ad_en;
  reg be_oe;
  reg abort_sig;
  reg count_rst_l, count_en_l;
  reg base_region0_l, base_region1_l;
  reg r_w_l;
  reg read_flag, single_read_flag;
 
  /*********************************************/
  /* begin statemachine declarations           */
  /* Note: synthesis attributes are synthesis  */
  /*       tool specific.                      */
  /*********************************************/
  
  reg [11:0] /* exemplar enum state_type */ cstate;
 
 
  parameter [11:0] /* exemplar enum state_type */

     idle =         12'b0000_0000_0001,
     con_wait =     12'b0000_0000_0010,
     con_wait2 =    12'b0000_0000_0100,
     con =          12'b0000_0000_1000,
     read_wait =    12'b0000_0001_0000,
     rw =           12'b0000_0010_0000,
     rw_wait =      12'b0000_0100_0000,
     rw_wait2 =     12'b0000_1000_0000,
     last_rw =      12'b0001_0000_0000,
     backoff =      12'b0010_0000_0000,
     retry =        12'b0100_0000_0000,
     abort =        12'b1000_0000_0000;

 /***********************************************/
 /* The following `defines are defined here to  */
 /* keep the state machine clean.               */
 /***********************************************/
 
 `define config_read (pci_cbe_l == 4'b1010)
 `define config_write (pci_cbe_l == 4'b1011)
 `define func_zero_type_zero (pci_ad[10:8] == 3'b000) && (pci_ad[1:0] == 2'b00)

 `define write_ba0 pci_addr[7:2] == 6'h10
 `define write_ba1 pci_addr[7:2] == 6'h14
 
 `define no_config (!pci_idsel && !pci_frame_l)
 `define io_read ((pci_cbe_l == 4'b0010)  && com[0]) 
 `define io_write ((pci_cbe_l == 4'b0011) && com[0])
 `define mem_read ((pci_cbe_l == 4'b0110) && com[1])
 `define mem_write ((pci_cbe_l == 4'b0111) && com[1])

 // Notice:  All outputs that go off the chip are registered,
 // except for data_write_l and data_read_l.
 // If an output is active low it ends with _l else it's
 // active high.
 
 // mealy state machine with synchronous outputs
 always @ (posedge pci_clk or negedge pci_rst_l)
   begin 
     if (!pci_rst_l) begin 
	 cstate <= #1 idle;
	 devsel_l <= #1 1; 
         trdy_l <= #1 1; 
	 stop_l <= #1 1;
	 pci_ad_oe <= #13 0; 
         dts_oe <= #13 0; 
	 par_oe <= #13 0; 
	 bk_oe <= #13 0; 
         abort_sig <= #1 0;
	 count_rst_l <= #1 1;
	 count_en_l <= #1 1;
	 base_region0_l <= #1 1;
	 base_region1_l <= #1 1;
	 r_w_l <= #1 1; // default to read
	 read_flag <= #1 0;
	 single_read_flag <= #1 0;
        end 
        else begin 
	 case (cstate) // parallel_case full_case
	   idle:
 	      begin 
	      	if ((`config_read || `config_write) && `func_zero_type_zero
		&& !pci_frame_l && pci_idsel) begin 
	      	  cstate <= #1 con_wait;
		  dts_oe <= #13 1; // takes 1 tic
	          if (`config_read) begin 
		    pci_ad_oe <= #13 1; // takes 1 tic
		  end
		  else begin // config write
		    pci_ad_oe <= #13 0; // takes 1 tic
		  end
		  par_oe <= #13 0;
		  devsel_l <= #1 1; // disabled at first
		  trdy_l <= #1 1; // disabled at first
		  stop_l <= #1 1; // disabled at first
		  count_rst_l <= #1 1;
	          count_en_l <= #1 1;
		  abort_sig <= #1 0; // disable
		  base_region0_l <= #1 1;
	          base_region1_l <= #1 1;
	          r_w_l <= #1 1;
		end

		else if ((`io_read || `mem_read) && `no_config ) begin 
		  cstate <= #1 rw_wait;
		  read_flag <= #1 1; // set because it's a read
		  dts_oe <= #13 1; // takes 1 tic get ready to drive
		  devsel_l <= #1 1; // disabled at first
		  trdy_l <= #1 1; // disabled at first
		  stop_l <= #1 1; // disabled at first
		  count_rst_l <= #1 0; // reset the counter
	          count_en_l <= #1 1;
		  abort_sig <= #1 0; // disable
		  base_region0_l <= #1 1;
	          base_region1_l <= #1 1;
	          r_w_l <= #1 1; // default to read
		end
		else if ((`io_write || `mem_write) && `no_config )begin 
		  cstate <= #1 rw_wait;
		  read_flag <= #1 0; // clear because it's a write
		  dts_oe <= #13 1; // takes 1 tic get ready to drive
		  devsel_l <= #1 1; // disabled at first
		  trdy_l <= #1 1; // disabled at first
		  stop_l <= #1 1; // disabled at first
		  count_rst_l <= #1 0; // reset the counter
	          count_en_l <= #1 1;
		  abort_sig <= #1 0; // disable
		  base_region0_l <= #1 1;
	          base_region1_l <= #1 1;
	          r_w_l <= #1 1; // default to a read at first
		end
		else begin 
		  cstate <= #1 idle;
	          devsel_l <= #1 1; 
                  trdy_l <= #1 1; 
	          stop_l <= #1 1;
	          pci_ad_oe <= #13 0; 
                  dts_oe <= #13 0; 
	          par_oe <= #13 0; 
	          bk_oe <= #13 0; 
                  abort_sig <= #1 0;
	          count_rst_l <= #1 1;
	          count_en_l <= #1 1;
		  abort_sig <= #1 0; // disable
		  base_region0_l <= #1 1;
	          base_region1_l <= #1 1;
	          r_w_l <= #1 1;
		end	      
	      end
	      
        con_wait: 
	      begin 
	         // always go to con_wait2
		 cstate <= con_wait2;
                 devsel_l <= #1 0;
	      end

	 con_wait2: 
	      begin 
		cstate <= con;
		par_oe <= #13 1; // takes one tic
 		trdy_l <= #1 0; // ready to transfer next tic
                if (!pci_frame_l)  
		  stop_l <= #1 0; // burst config not supported
		                  // disconnect A or B
		else
		  stop_l <= #1 1; // single Config is OK
	      end

	 con:
	      begin 
		if (!pci_irdy_l) begin 
		  // transfer data
		  cstate <= backoff;
		  devsel_l <= #1 1;
		  trdy_l <= #1 1;
		  stop_l <= #1 1;
		  pci_ad_oe <= #13 0; // disable
		end
		else begin 
		  // wait for pci_irdy_l == 0
		  cstate <= con;
		  devsel_l <= #1 0;
		  trdy_l <= #1 0;
		  if (!pci_frame_l)  
		    stop_l <= #1 0; // burst config not supported
		                    // disconnect A or B
		  else
 		    stop_l <= #1 1; // single Config is OK
		end
	      end

          /* if we have a hit rw_wait turns on dts_oe.
	     and asserts the base address region signal.
	     we need to wait till rw_wait2 to change
	     any dts signal.
	     d=devsel_l t=trdy_l s=stop_l
	  */   

   	  rw_wait:
    	     begin 
	
	       if (pci_frame_l && read_flag) begin 
		     single_read_flag <= #1 1; // single cycle read
	           end
	           else begin 
		     single_read_flag <= #1 0; // i.e. burst read
	           end
	       // Irdy_l can not be late, the initiator must be ready
	       // here. The target relies on it.
	       if (!hit_ba0_l) begin 
	           cstate <= #1 rw_wait2;
	           count_rst_l <= #1 1; // disable
		   count_en_l <= #1 0; // enable
		   base_region0_l <= #1 0; // enable
		   base_region1_l <= #1 1; // disable
		   dts_oe <= #13 1; // takes 1 tic get ready to drive
		   devsel_l <= #1 1; // disabled at first
		   trdy_l <= #1 1; // disabled at first
		   stop_l <= #1 1; // disabled at first
		   if (read_flag) begin 
		     bk_oe <= #13 0; // disable OE
		     r_w_l <= #1 1;
		     end
		   else begin 
		     bk_oe <= #13 1; // enable OE
		     r_w_l <= #1 0;
		   end 
		end
		else if (!hit_ba1_l) begin 
		   cstate <= #1 rw_wait2;
	           count_rst_l <= #1 1; // disable
		   count_en_l <= #1 0; // enable

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -