PCI总线目标接口状态机设计

时间:2023-11-09 18:07:32

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; 

  output trdy_l; 

  output stop_l; 

  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

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;

 

  

  reg [11:0] cstate;

 

 

  parameter [11:0]

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;

`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])

// mealy state machine 

 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; 


read_flag <= #1 0;


single_read_flag <= #1 0;

        end 

        else begin 


case (cstate) 


  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;


         if (`config_read) begin 


   pci_ad_oe <= #13 1; 


 end


 else begin 


   pci_ad_oe <= #13 0; 


 end


 par_oe <= #13 0;


 devsel_l <= #1 1;


 trdy_l <= #1 1; 


 stop_l <= #1 1; 


 count_rst_l <= #1 1;


         count_en_l <= #1 1;


 abort_sig <= #1 0;


 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; 


 dts_oe <= #13 1; 


 devsel_l <= #1 1; 


 trdy_l <= #1 1;


 stop_l <= #1 1; 


 count_rst_l <= #1 0; 


         count_en_l <= #1 1;


 abort_sig <= #1 0; 


 base_region0_l <= #1 1;


         base_region1_l <= #1 1;


         r_w_l <= #1 1;


end


else if ((`io_write || `mem_write) && `no_config )begin 


 cstate <= #1 rw_wait;


 read_flag <= #1 0; 


 dts_oe <= #13 1; 


 devsel_l <= #1 1;


 trdy_l <= #1 1; 


 stop_l <= #1 1; 


 count_rst_l <= #1 0;


         count_en_l <= #1 1;


 abort_sig <= #1 0; 


 base_region0_l <= #1 1;


         base_region1_l <= #1 1;


         r_w_l <= #1 1; 


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; 


 base_region0_l <= #1 1;


         base_region1_l <= #1 1;


         r_w_l <= #1 1;


end
     


     end


     

        con_wait: 


     begin 


        cstate <= con_wait2;

                 devsel_l <= #1 0;


     end

con_wait2: 


     begin 


cstate <= con;


par_oe <= #13 1; 

 
trdy_l <= #1 0; 

                if (!pci_frame_l)  


 stop_l <= #1 0; 


                


else


 stop_l <= #1 1; 


     end

con:


     begin 


if (!pci_irdy_l) begin 


 


 cstate <= backoff;


 devsel_l <= #1 1;


 trdy_l <= #1 1;


 stop_l <= #1 1;


 pci_ad_oe <= #13 0;


end


else begin 


 


 cstate <= con;


 devsel_l <= #1 0;


 trdy_l <= #1 0;


 if (!pci_frame_l)  


   stop_l <= #1 0; 


                  


 else

 
   stop_l <= #1 1; 


end


     end

rw_wait:

   
    begin

if (pci_frame_l && read_flag) begin 


    single_read_flag <= #1 1;


          end


          else begin 


    single_read_flag <= #1 0; 


          end

if (!hit_ba0_l) begin 


          cstate <= #1 rw_wait2;


          count_rst_l <= #1 1;


  count_en_l <= #1 0; 


  base_region0_l <= #1 0;


  base_region1_l <= #1 1;


  dts_oe <= #13 1; 


  devsel_l <= #1 1; 


  trdy_l <= #1 1; 


  stop_l <= #1 1;


  if (read_flag) begin 


    bk_oe <= #13 0;


    r_w_l <= #1 1;


    end


  else begin 


    bk_oe <= #13 1; 


    r_w_l <= #1 0;


  end 


end


else if (!hit_ba1_l) begin 


  cstate <= #1 rw_wait2;


          count_rst_l <= #1 1;


  count_en_l <= #1 0;


  base_region0_l <= #1 1; 


  base_region1_l <= #1 0;


  dts_oe <= #13 1; 


  devsel_l <= #1 1; 


  trdy_l <= #1 1; 


  stop_l <= #1 1; 


  if (read_flag) begin 


    bk_oe <= #13 0; 


    r_w_l <= #1 1;


    end


  else begin 


    bk_oe <= #13 1; 


    r_w_l <= #1 0;


  end 


end


else begin 


  cstate <= #1 idle;


  bk_oe <= #13 0;  


          count_rst_l <= #1 1; 


  count_en_l <= #1 1;


  r_w_l <= #1 1;


  base_region0_l <= #1 1;


  base_region1_l <= #1 1; 


  dts_oe <= #13 0; 


  devsel_l <= #1 1; 


  trdy_l <= #1 1;


  stop_l <= #1 1;


end


    end

rw_wait2: // don't monitor abort here


     begin

if (read_flag) begin 


         pci_ad_oe <= #13 1;


 par_oe <= #13 1;


 end


else begin 

                  pci_ad_oe <= #13 0; 


end

if (!retry_l) begin 


 // retry timeout


 cstate <= #1 retry;


 devsel_l <= #1 0; 


 trdy_l <= #1 1; 


 stop_l <= #1 0; 


end


else if (retry_l && !ready_l && !pci_frame_l && data_stop_l) begin 


 // normal burst write or read with no timeout or stop


 devsel_l <= #1 0; 


 stop_l <= #1 1; 

                  if (read_flag) begin 


   cstate <= read_wait;


   trdy_l <= #1 1;


 end


 else begin 


   cstate <= rw;


   trdy_l <= #1 0;


 end


end


else if (retry_l && !ready_l && pci_frame_l) begin 


 // single read or write with no timeout & stop is don't care


 devsel_l <= #1 0; 


 stop_l <= #1 1;

 
 if (read_flag) begin 


   cstate <= read_wait;


   trdy_l <= #1 1;


 end


 else begin 


   cstate <= last_rw;


   trdy_l <= #1 0;


 end


end


else if (retry_l && !ready_l && !data_stop_l) begin 


 // single read or write & backend only wants one cycle


 if (read_flag ) begin 


   cstate <= read_wait;


   devsel_l <= #1 0; 


           trdy_l <= #1 1;


   stop_l <= #1 1;


 end


 else begin 


   cstate <= last_rw; 


   devsel_l <= #1 0; 


   trdy_l <= #1 0; 


   stop_l <= #1 0; 


 end


end


else if (retry_l && ready_l) begin 


 // enable retry counter


 cstate <= #1 rw_wait2;


 count_en_l <= #1 0;


 devsel_l <= #1 0; 


 trdy_l <= #1 1; 


 stop_l <= #1 1; 


end


else if (!bkend_abort_l) begin 


 cstate <= #1 abort;


 devsel_l <= #1 1; 


 trdy_l <= #1 1; 


 stop_l <= #1 0;

 
 abort_sig <= #1 1;


end


else begin 


 cstate <= rw_wait2;


end


     


     end

read_wait: 

 
  //This state is used to READ the first piece of data


     begin   


        if ( !bkend_abort_l) begin 


  cstate <= #1 abort;


  devsel_l <= #1 1; 


  trdy_l <= #1 1; 


  stop_l <= #1 0;


  bk_oe <= #13 0;


  base_region0_l <= #1 1; 


  base_region1_l <= #1 1; 


  abort_sig <= #1 1;


end


else if (!pci_frame_l && bkend_abort_l && data_stop_l) begin 


  cstate <= #1 rw; 


  devsel_l <= #1 0; 


  trdy_l <= #1 0; 


  stop_l <= #1 1; 


end


        else if (pci_frame_l && bkend_abort_l && data_stop_l) begin 


  cstate <= #1 last_rw; 


  devsel_l <= #1 0; 


  trdy_l <= #1 0; 


  stop_l <= #1 1;


end


 


else if (!data_stop_l) begin 


  cstate <= last_rw;


  devsel_l <= #1 0; 


  trdy_l <= #1 0; 


  stop_l <= #1 0;


  bk_oe <= #13 0;


end


else  begin 


  cstate <= idle;


end


 
    


     end

rw:


     begin 


       if ( !bkend_abort_l) begin 


  cstate <= #1 abort;


  devsel_l <= #1 1; 


  trdy_l <= #1 1; 


  stop_l <= #1 0;

 
  bk_oe <= #13 0;  


  base_region0_l <= #1 1; 


  base_region1_l <= #1 1; 


  abort_sig <= #1 1;


end


else if (!pci_frame_l && bkend_abort_l && data_stop_l) begin 


  cstate <= #1 rw;


  devsel_l <= #1 0; 


  trdy_l <= #1 0; 


  stop_l <= #1 1; 


end


else if (pci_frame_l && bkend_abort_l && data_stop_l) begin 


  cstate <= #1 backoff;


  devsel_l <= #1 1; 


  trdy_l <= #1 1; 


  stop_l <= #1 1;


  pci_ad_oe <= #13 0;

 
  bk_oe <= #13 0;  


  base_region0_l <= #1 1; 


  base_region1_l <= #1 1; 


end


else if (pci_frame_l && !data_stop_l) begin 


  cstate <= backoff;


  devsel_l <= #1 1; 


  trdy_l <= #1 1; 


  stop_l <= #1 1;


  bk_oe <= #13 0;  

                   base_region0_l <= #1 1; 


  base_region1_l <= #1 1; 


end


else if (!data_stop_l) begin 


  cstate <= last_rw; 


  devsel_l <= #1 0; 


  trdy_l <= #1 0; 


  stop_l <= #1 0;


end


else  begin 


  cstate <= idle;


end


 
    


     end


 last_rw:

 
     begin 


if (pci_frame_l) begin 


 // pci_frame_l end gracefully


 cstate <= backoff;


 devsel_l <= #1 1; 


 trdy_l <= #1 1; 


 stop_l <= #1 1;

                  bk_oe <= #13 0;  


 pci_ad_oe <= #13 0;

                  base_region0_l <= #1 1; 


 base_region1_l <= #1 1; 


end


else if (!pci_frame_l) begin 


 cstate <= last_rw; 


 devsel_l <= #1 0; 

 
 trdy_l <= #1 1;


 stop_l <= #1 0;


end


else begin 

                  cstate <= idle;


end
    


     end


retry:

   
     begin


       if (!pci_frame_l) begin 


 cstate <= retry;


 dts_oe <= #13 1; 


 devsel_l <= #1 0; 


 trdy_l <= #1 1; 


 stop_l <= #1 0;

 
 bk_oe <= #13 0;  

                  base_region0_l <= #1 1; 


 base_region1_l <= #1 1;   


end


else if (pci_frame_l) begin 


 cstate <= backoff;


 devsel_l <= #1 1; 


 trdy_l <= #1 1; 


 stop_l <= #1 1;

                  bk_oe <= #13 0; 

 
 pci_ad_oe <= #13 0;


 base_region0_l <= #1 1; 


 base_region1_l <= #1 1;  


end


     end

abort:


     begin 


if (!pci_frame_l) begin 


 cstate <= abort;


 devsel_l <= #1 1; 


 trdy_l <= #1 1; 


 stop_l <= #1 0;


 abort_sig <= #1 0;


end


else if (pci_frame_l) begin 


 cstate <= backoff;


 devsel_l <= #1 1; 


 trdy_l <= #1 1; 


 stop_l <= #1 1;


 bk_oe <= #13 0;


 pci_ad_oe <= #13 0;


 abort_sig <= #1 0; 


end


     end


backoff:

   
     begin 


cstate <= idle;


pci_ad_oe <= #13 0; 


dts_oe <= #13 0; 


par_oe <= #13 0; 


bk_oe <=#13 0; 


     end

default:


     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;


     end


endcase

       end

   

   end

 

always @ (cstate)

  begin 

    if (cstate == idle || cstate == backoff) begin 

        be_oe <= #1 0;

      end

      else begin 


be_oe <= #1 1;

      end

  

  end

always @ (pci_frame_l or cstate)

  begin 

    if (cstate == idle && !pci_frame_l) begin 

        pci_ad_en <= #1 1;

      end

      else begin 


pci_ad_en <= #1 0;

      end

  

  end

assign #1 data_write_l = (!trdy_l && !pci_irdy_l && !read_flag && !ready_l) ? 0 : 1;

assign #1 data_read_l = ( (single_read_flag && (cstate == rw_wait2) && !ready_l ) || (!single_read_flag && read_flag && !pci_frame_l && !pci_irdy_l && !ready_l && (cstate == rw_wait2 || cstate == rw || cstate == last_rw || cstate == abort)) ) ? 0 : 1;       

 

endmodule