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

📄 bkend_daemon.v

📁 pci 接口协议 用Verilog编写
💻 V
字号:
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> 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.                 1/18/98      Initial Creation
// --------------------------------------------------------------------
//
//	Module  bkend_daemon
// 
// This block is a daemon or behavioral model used to model the 
// functionality of a generic bkend device.  Any back end device 
// if it's an SDRAM, SRAM, FIFO or simple I/O device will need
// control logic to arbitrate the backend signals from the PCI 
// Target state machine.
// This daemon simply arbitrates the bkend signals, and reads and 
// writes the data appropriatly.  Depending on the address and bank written to,
// this daemon will respond normally, with a retry, a stop, an abort or an interupt.
//
// All reads and writes to bk0 will function normally.  Bk1 has added
// functionality to test a retry, a stop, and an abort.
//
// If a write is made to address 20'h000A0 and bk1 the daemon will not 
// respond with ready_l hence causing a data retry.
//
// If a write is made to address 20'h000B0 and bk1 the daemon will start 
// the cycle then respond with data_stop_l == 0 causing a data stop.
//
// If a write is made to address 20'h000C0 and bk1 the daemon will start
// the cycle, but respond with bkend_abort_l == 0 causing a abort.
// 
// If a write is made to address 20'h000D0 and bk1 the daemon will run
// the cycle, but respond with bkend_int_l == 0 causing a interruptto be
// passed through the PCI Target.
//
// If a write is made to address 20'h000E0 and bk1 the daemon will run
// the cycle, but respond with bkend_int_l == 1 causing the interruptto be
// disabled.
//
//
//
// NOTE:  1) To use the special features of bk1 the cycle must start with the
//        specified address.  In WILL burst by it with no effect.
// 
///////////////////////////////////////////////////////////////////////////////////

`timescale 1ns / 1ps



module bkend_daemon (bkend_ad, be_l, base_region0_l, base_region1_l, r_w_l, 
    bkend_dat, ready_l, data_write_l, data_read_l, data_stop_l, bkend_int_l,
    bkend_abort_l, pci_clk, pci_rst_l);
 
  input [19:0] bkend_ad;
  input [3:0] be_l; // not used
  input base_region0_l;
  input base_region1_l;
  input r_w_l;
  input data_write_l; // used as a write strobe for the clock
  input data_read_l; // used as a read strobe for the clock
  input pci_clk;
  input pci_rst_l;
  inout [31:0] bkend_dat;
  output ready_l;
  output data_stop_l;
  output bkend_int_l;
  output bkend_abort_l;

  // register declarations
  reg [31:0] bkend_dat_reg;
  reg [31:0] bk0 [63:0]; // 64 32 bit memory locations
  reg [31:0] bk1 [63:0]; 
  reg ready_l, data_stop_l, bkend_int_l, bkend_abort_l;
  reg [3:0] state; // current state variable
  reg [19:0] count; // the address counter
  reg data_stop_flag, data_abort_flag;
  
  // integer declarations
  integer i;
  
 // daemon state machine variables
 parameter [3:0] idle = 4'h0,
                 first_data = 4'h1,
		 ready = 4'h2,
		 data_stop = 4'h3,
		 data_abort = 4'h4;
		 
// The following block resets the memory banks
initial
begin 
  $display("  %m  \t \t  << Initializing Bkend memory banks 0 & 1 >>");
  for ( i= 0; i < 64; i = i+1) begin 
    #1;
    bk0[i] = 32'h0;
    bk1[i] = 32'h0;
  end // end of for loop
  bkend_dat_reg = 32'b0;
  data_stop_flag = 0;
  data_abort_flag = 0;
end


// assigning the bkend_dat_reg to the output port bkend_dat
assign #4 bkend_dat = (r_w_l && (!base_region0_l || !base_region1_l))  ? bkend_dat_reg : 32'hZ;

// The following block of code controls the reads
// and writes to both bk0 and bk1.  Note that on any
// given data cycle the state machine cycles from
// first_data to ready.  It stays in ready for a burst
// and returns to idle at the end of the cycle.

always @ (posedge pci_clk)
  begin 
     if (r_w_l && (state == first_data)  && !data_read_l) begin 
       count = bkend_ad; // read address
       if (!base_region0_l) begin 
	 bkend_dat_reg = bk0[count[19:2]];
	 $display($time, "  %m  \t \t \t  << Target reading bk0[%h] = %h >>", count, bkend_dat_reg);
       end
       else if (!base_region1_l) begin 
	 bkend_dat_reg = bk1[count[19:2]];
	 $display($time, "  %m  \t \t \t << Target reading bk1[%h] = %h >>", count, bkend_dat_reg);
       end
     end
     else if (r_w_l && (state == ready || state == data_stop || state == data_abort) && !data_read_l ) begin
       count = count + 4; // burst read
       if (!base_region0_l) begin 
	 bkend_dat_reg = bk0[count[19:2]];
	 $display($time, "  %m  \t \t \t << Target reading bk0[%h] = %h >>", count, bkend_dat_reg);
       end
       else if (!base_region1_l) begin  
	 bkend_dat_reg = bk1[count[19:2]];
	 $display($time, "  %m  \t \t \t << Target reading bk1[%h] = %h >>", count, bkend_dat_reg);
       end
     end
     else if (!r_w_l && (state == first_data) && !data_write_l) begin 
       count = bkend_ad; // write address
       if (!base_region0_l) begin 
	 bk0[count[19:2]] = bkend_dat;
	 $display($time, "  %m  \t \t \t << Target writing bk0[%h] = %h >>", count, bkend_dat);
       end
       else if (!base_region1_l) begin 
	 bk1[count[19:2]] = bkend_dat;
	 $display($time, "  %m  \t \t \t << Target writing bk1[%h] = %h >>", count, bkend_dat);
       end
     end
     else if (!r_w_l && (state == ready || state == data_stop || state == data_abort) && !data_write_l ) begin
       count = count + 4; // burst write
       if (!base_region0_l) begin 
	 bk0[count[19:2]] = bkend_dat;
	 $display($time, "  %m  \t \t \t << Target writing bk0[%h] = %h >>", count, bkend_dat);
       end
       else if (!base_region1_l) begin 
	 bk1[count[19:2]] = bkend_dat;
	 $display($time, "  %m  \t \t \t << Target writing bk1[%h] = %h >>", count, bkend_dat);
       end
     end
   end

 
// The following block is the behavioral state machine
// it controls the arbitration of all bkend control signals to
// the PCI target.
//
// On a normal read or write cycle the state machine will cycle from:
// idle -> first_data -> ready -> ready || idle
//
// If the cycle is a special cycle initiating a stop or an abort
// it will cycle from:
// idle -> first_data -> ready -> data_stop||data_abort -> data_stop||data_abort||idle
//
// On a retry it will cycle from:
// idle -> idle never responding which initiates a retry
// 
// On an interruptit will cycle from:
// idle -> first_data -> ready -> ready || idle
//

 always @ (posedge pci_clk or negedge pci_rst_l)
   begin 
     if (pci_rst_l == 1'b0) begin 
        state = #1 idle;
 	ready_l = #1 1; // bkend is not ready
        data_stop_l = #1 1'bZ;
	bkend_int_l = #1 1;
 	bkend_abort_l = #1 1;
	data_stop_flag = #1 0; //disabled
        data_abort_flag = #1 0; //disabled
       end
       else begin 
	 case (state)
	   idle: begin 
	           if (!base_region0_l)
		     begin 
		       state = #1 first_data;
		       ready_l = #1 0; // bkend is ready
		       data_stop_l = #1 1'bZ;
 		       bkend_abort_l = #1 1;
		       data_stop_flag = #1 0; //disabled
                       data_abort_flag = #1 0; //disabled
                     end
	           else if (!base_region1_l && bkend_ad == 20'h000A0)
		     begin // initiate a Retry
	               state = #1 idle;
		       ready_l = #1 1; // bkend is NOT ready
		       data_stop_l = #1 1'bZ;
 		       bkend_abort_l = #1 1;
		       data_stop_flag = #1 0; //disabled
                       data_abort_flag = #1 0; //disabled
                     end
	           else if (!base_region1_l && bkend_ad == 20'h000B0)
		     begin // initiate a data stop
	               state = #1 first_data;
		       ready_l = #1 0; // bkend is ready
		       data_stop_l = #1 1'bZ;
 		       bkend_abort_l = #1 1;
		       data_stop_flag = #1 1; // flag a stop
                       data_abort_flag = #1 0; //disabled
                     end
	           else if (!base_region1_l && bkend_ad == 20'h000C0)
		     begin // initiate a data abort 
	               state = #1 first_data;
		       ready_l = #1 0; // bkend is ready
		       data_stop_l = #1 1'bZ;
 		       bkend_abort_l = #1 1;
		       data_stop_flag = #1 0; //disabled
                       data_abort_flag = #1 1; // flag an abort
                     end
	           else if (!base_region1_l && bkend_ad == 20'h000D0)
		     begin // initiate an interrupt
	               state = #1 first_data;
		       ready_l = #1 0; // bkend is ready
		       data_stop_l = #1 1'bZ;
		       bkend_int_l = #1 0; // initiate an interupt
 		       bkend_abort_l = #1 1;
		       data_stop_flag = #1 0; //disabled
                       data_abort_flag = #1 0; //disabled
                     end
                   else if (!base_region1_l && bkend_ad == 20'h000E0)
		     begin // disable the interrupt
	               state = #1 first_data;
		       ready_l = #1 0; // bkend is ready
		       data_stop_l = #1 1'bZ;
		       bkend_int_l = #1 1; // disable the interupt
 		       bkend_abort_l = #1 1;
		       data_stop_flag = #1 0; //disabled
                       data_abort_flag = #1 0; //disabled
                     end
	           else if (!base_region1_l)
		     begin // just a normal base_region1_l access
	               state = #1 first_data;
		       ready_l = #1 0; // bkend is ready
		       data_stop_l = #1 1'bZ;
 		       bkend_abort_l = #1 1;
		       data_stop_flag = 0; //disabled
                       data_abort_flag = 0; //disabled
                     end
		   else 
		     begin // stay in idle no accesses made
	               state = #1 idle;
		       ready_l = #1 1;
		       data_stop_l = #1 1'bZ;
 		       bkend_abort_l = #1 1;
		       data_stop_flag = 0; //disabled
                       data_abort_flag = 0; //disabled
		     end
	          end
		  
	   first_data: begin 
	                 if (base_region0_l && base_region1_l) begin 
			   $display("  %m  \t \t This Shouldn't happen??!!!");
      	                   state = #1 idle; 
		           ready_l = #1 1;
		           data_stop_l = #1 1'bZ;
 		           bkend_abort_l = #1 1;
		         end
		         else if (!base_region0_l && (!data_write_l || !data_read_l)) begin
		           state = #1 ready;
			   ready_l = #1 0; // bkend is ready
		           data_stop_l = #1 1'bZ;
 		           bkend_abort_l = #1 1;
		         end
		         else if (!base_region1_l && (!data_write_l || !data_read_l)) begin
		           state = #1 ready;
			   ready_l = #1 0; // bkend is ready
		           data_stop_l = #1 1'bZ;
 		           bkend_abort_l = #1 1;
	                 end
			 else begin // waiting to transfer first data
			   state = #1 first_data;
			   ready_l = #1 0; // bkend is ready
		           data_stop_l = #1 1'bZ;
 		           bkend_abort_l = #1 1;
			 end
		       end
	   ready: begin 
	              if (!base_region0_l) begin 
			state = #1 ready; // bursting
			ready_l = #1 0; // bkend is ready
		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1;
		      end
		      else if (!base_region1_l && data_stop_flag) begin 
			state = #1 data_stop; 
			ready_l = #1 0; 
		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1;
		      end
		      else if (!base_region1_l && data_abort_flag) begin 
			state = #1 data_abort; 
			ready_l = #1 0; 
		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1;
		      end
		      else if (!base_region1_l) begin 
			state = #1 ready; // bursting
			ready_l = #1 0; // bkend is ready
		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1;
		      end
		      else begin // cycle is over 
		        state = #1 idle;
			ready_l = #1 1;
      		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1;
		      end	
	          end
           data_stop: begin 
	               if (!base_region1_l) begin 
			state = data_stop; // bursting & trying to stop
			ready_l = #1 0; // bkend is ready
		        data_stop_l = #1 0; // initiate stop
 		        bkend_abort_l = #1 1;
			data_stop_flag = #1 0;
			data_abort_flag = #1 0;
		      end
		      else begin // Target acknowledged stop & removed !base_region1_l 
		        state = idle;
			ready_l = #1 1;
      		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1;
			data_stop_flag = #1 0;
			data_abort_flag = #1 0;
		      end	
	          end 
	   data_abort: begin 
	               if (!base_region1_l) begin 
			state = data_abort; // bursting & trying to abort
			ready_l = #1 0; // bkend is ready
		        data_stop_l = #1 1'bZ; 
 		        bkend_abort_l = #1 0; // catostrophic failure abort!
			data_stop_flag = #1 0; // disabled
			data_abort_flag = #1 0; // disabled
		      end
		      else begin // Target acknowledged abort & removed !base_region1_l 
		        state = idle;
			ready_l = #1 1;
      		        data_stop_l = #1 1'bZ;
 		        bkend_abort_l = #1 1; // disable abort
			data_stop_flag = #1 0; // disabled
			data_abort_flag = #1 0; // disabled
		      end	
	          end 
	   default: begin 
	               $display("  %m  \t \t << Something is hosed, bkend SM going to idle >> ");
		       state = idle;
	   
	            end
	 endcase
       end
   
   end

endmodule //of bkend_daemon




⌨️ 快捷键说明

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