/*-----------------------------------------------------------------------------
--
--                       (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              : spi3mon.v
--   Author            : Mike Hammer, Vishnu Balaraman
--
--   Date              : 01.28.02
--   Update            : 
--   Brief Description : 
--		       : 
--		       : 
--		       : 
-- --------------------------------------------------------------------------*/
`timescale 1 ns/ 100 ps
module spi3mon (
	
	rfclk,
	renb,
	rxdat,
	rmod,
	rprty,
	rval,
	rsop,
	reop,
	rerr,
	rsx,
	
	reset,
	bankid
);

parameter	burst = 64;//16,32,64,128
parameter	ports = 4;//1,2,4,8,16,32
parameter	pause = 0;//2
			
input		rfclk;
input		renb;
input	[31:0]	rxdat;
input	[1:0]	rmod;
input		rval;
input		rsop;
input		reop;
input		rerr;
input		rprty;
input		rsx;
input		reset;
input   [1:0]   bankid;

reg             renb_ff;
reg		open[ports-1:0];
reg     [7:0]   portid;
reg     [7:0]   pid;
reg     [7:0]   offset;
integer         i;
//integer         log_file;
integer		wcnt[ports-1:0];// counts words(4 bytes) in a packet
integer		bcnt;// counts words(4 bytes) in a burst

/*initial begin

   log_file = $fopen ("sim.log");

   #10000000

   $fclose(log_file);

end*/

function check_parity;

input   [31:0]   data;
input            rsx;
input            rval;
input            rprty;

reg              parity;

begin
   if (rval | rsx) begin
//      parity = ~(^data[31:0]);
      parity = (^data[31:0]);
   end
   else begin
      //to prevent errors being reported when parity is not valid
      parity = rprty;
   end
   
   assign check_parity = (parity == rprty) ? 1'b1 : 1'b0;  

end

endfunction

always @(posedge rfclk or reset) begin

   if (!reset) begin
      bcnt <= 8'b0;
      for (i = 0;i < ports;i = i + 1) begin
         wcnt[i] <= 'b0;
         open[i] <= 1'b0;
      end
      portid <= 8'b0;
      pid <= 8'b0;
      offset <= 8'b0;
      renb_ff <= 1'b1;
   end
   else begin

      renb_ff <= renb;
      
      offset <= (bankid << 2);
      
      if (check_parity(rxdat,rsx,rval,rprty) == 1'b0) begin
         $fdisplay(log_file,"%t : bad parity on port =%d",$time,portid);
      end
      
      if (~renb_ff) begin

         if (rval) begin
         
            if (reop) begin
               bcnt <= 8'b0;
               wcnt[pid] <= 'b0;
            end
            else if (rsop) begin
               bcnt <= 8'b1;
               wcnt[pid] <= 'b1;
            end
            else if (bcnt == (burst - 1)) begin
              bcnt <= 8'b0;
              wcnt[pid] <= wcnt[pid] + 1;
            end
            else begin
               bcnt <= bcnt + 1;
               wcnt[pid] <= wcnt[pid] + 1;
            end
         
            if (reop && rsop) begin
               open[pid] <= 1'b0;
               //$fdisplay(log_file,"%t : port %d packet size %d",$time,portid,(wcnt[pid] + 1));
            end
            else if (rsop) begin
               open[pid] <= 1'b1;
               if (open[pid] == 1'b1) begin
                  $fdisplay(log_file,"%t : consecutive sops detected on port (bank) =%d (%d)",$time,portid,bankid);
               end
            end
            else if (reop) begin
               open[pid] <= 1'b0;
               if (open[pid] == 1'b1) begin               
                  //$fdisplay(log_file,"%t : port %d packet size %d",$time,portid,(wcnt[pid] + 1));
               end
               else begin
                  $fdisplay(log_file,"%t : consecutive eops detected on port (bank) %d (%d)",$time,portid,bankid);
               end
            end

         end

         else if (rsx) begin

            portid <= rxdat[7:0];
            pid <= (rxdat[7:0] - offset);
            bcnt <= 8'b0;
            if ((bcnt !== (burst - 1)) && (bcnt !== 8'b0)) begin
               $fdisplay(log_file,"%t : incorrect burst size",$time);               
            end

         end

         else begin

            if (bcnt !== 8'b0) begin
               $fdisplay(log_file,"%t : incorrect burst size",$time);
            end               

         end
      
      end
   
   end

end


endmodule


//check parity;flag consecutive sop on a single port without eop in between;
//flag consecutive eop on a single port without sop in between;check burst size
//- rval shouldn't be low and rsx shouldn't be active within a burst;rmod by 
//pattern matching;check 0/2 pause condition

