/*-----------------------------------------------------------------------------
--
--                       (C) COPYRIGHT 2002
--                      Lattice Semiconductor		
--                       ALL RIGHTS RESERVED	
--
--	  The code is copyright protected and may not be modified, reproduced
--        or used without written permission of Lattice Semiconductor 
--
--
--   File              : bmaster.v
--   Author            : Mike Hammer, Vishnu Balaraman
--
--   Date              : 01.21.03
--   Update            : 
--
--   Brief Description : 
--		       : 
--		       : 
--		       : 
-- --------------------------------------------------------------------------*/
`timescale 1 ns/100 ps

`define FAIL  1'b1
`define PASS  1'b0
`define SYS_DATA	36  // system bus data bus size
`define SYS_ADDR	18  // system bus address bus size
`define SYS_SIZE	2  // system bus transfer size

module bmaster(
   mpi_clk,
   mpi_tsz,
   mpi_rdwr_n,
   mpi_burst,
   mpi_bdip,
   mpi_strbn,
   cs0n,
   cs1,
   mpi_addr,
   mpi_data,
   mpi_ta,
   mpi_tea,
   mpi_irq,
   mpi_retry
);

input              mpi_clk;
output   [1:0]     mpi_tsz;
output             mpi_rdwr_n;
output             mpi_burst;
output             mpi_bdip;
output             mpi_strbn;
output             cs0n;
output             cs1;
output   [17:0]    mpi_addr;
inout    [7:0]     mpi_data;
input              mpi_ta;
input              mpi_tea;
input              mpi_irq;
input              mpi_retry;

reg   [1:0]     mpi_tsz;
reg             mpi_burst;
reg             mpi_bdip;

reg             mpi_rdwr_n;
reg             mpi_strbn;
reg             cs0n;
reg             cs1;
reg   [17:0]    mpi_addr;
reg   [7:0]     wrdata_TRI;
reg             wr;

initial begin
   mpi_burst = 1'b1;
   mpi_bdip = 1'b1;
   mpi_tsz = 2'b01;
   
   mpi_strbn = 1'b1;
   mpi_rdwr_n = 1'b1;
   cs0n = 1'b1;
   cs1 = 1'b0;
   mpi_addr = 18'h00000;
   
   wrdata_TRI = 8'bz;
   wr = 1'b0;
end

assign mpi_data = (wr) ? wrdata_TRI : 8'bz; 

task single_write;

input [`SYS_ADDR-1:0] address;
input [`SYS_SIZE-1:0] size;
input [`SYS_DATA-1:0] data;
inout ret_status;

reg status;
reg ret_status;

begin
   
   status = `PASS;
   
   if (!status) begin
      
      @(posedge mpi_clk);
      
      mpi_strbn = 1'b0;
      cs0n = 1'b0;
      cs1 = 1'b1;
      mpi_rdwr_n = 1'b0;
      mpi_addr = address;

      // if (mpi_addr < 18'h31000) begin
      // if (!address[12]) begin

         wrdata_TRI[7] = data[0];
         wrdata_TRI[6] = data[1];
         wrdata_TRI[5] = data[2];
         wrdata_TRI[4] = data[3];
         wrdata_TRI[3] = data[4];
         wrdata_TRI[2] = data[5];
         wrdata_TRI[1] = data[6];
         wrdata_TRI[0] = data[7];
      // end
      // else
      //    wrdata_TRI = data;
	
      wr = 1'b1;
      
      @(posedge mpi_clk);
      
      mpi_strbn = 1'b1;

      // wait for an acknowledge and then wait two MPI clock
      @ (negedge mpi_ta); 
      repeat (2) @ (posedge mpi_clk);
      
      mpi_rdwr_n = 1'b1;
      @ (posedge mpi_clk);
      cs0n = 1'b1;
      cs1 = 1'b0;
      wrdata_TRI = 8'bz;
      
      repeat (60) @(posedge mpi_clk);
      
      wr = 1'b0;
      status = 	`PASS;
                  
   end
   
   ret_status = ret_status | status;
   
end

endtask

task single_read;

input [`SYS_ADDR-1:0] address;
input [`SYS_SIZE-1:0] size;
output [`SYS_DATA-1:0] data;
inout ret_status;

reg status;
reg ret_status;

begin
   
   status = `PASS;
   
   if (!status) begin
   
      @(posedge mpi_clk);
      
      mpi_strbn = 1'b0;
      cs0n = 1'b0;
      cs1 = 1'b1;
      mpi_rdwr_n = 1'b1;
      mpi_addr = address;
      
      @(posedge mpi_clk);
      
      mpi_strbn = 1'b1;
      
      @(posedge mpi_clk);
      
      // wait for an acknowledge and then wait one MPI clock
      @(negedge mpi_ta);
      @(posedge mpi_clk);
//      cs0n = 1'b1;
//      cs1 = 1'b0;

      // if (mpi_addr < 18'h31000) begin
      // if (!address[12]) begin

          data[7] = mpi_data[0];
          data[6] = mpi_data[1];
          data[5] = mpi_data[2];
          data[4] = mpi_data[3];
          data[3] = mpi_data[4];
          data[2] = mpi_data[5];
          data[1] = mpi_data[6];
          data[0] = mpi_data[7];
      // end
      // else
      //     data = mpi_data;


      @(posedge mpi_clk);
      cs0n = 1'b1;
      cs1 = 1'b0;
      
      @(posedge mpi_clk);
      
      status = `PASS;
            
   end
   
   ret_status = ret_status | status;
   
end

endtask

endmodule
