
`timescale 1ps / 1ps
module CoreTSE_ahb_tb 
(  
   mdc,            
   mdo,            
   mdoen,          
   ahb_hrdata,     
   ahb_hresp,      
   ahb_hreadyo,    
   ahb_txhbusreq,  
   ahb_rxhbusreq,  
   ahb_txhtransm,  
   ahb_rxhtransm,  
   ahb_txhaddrm,   
   ahb_rxhaddrm,   
   ahb_txhwritem,  
   ahb_rxhwritem,  
   ahb_txhwdatam,  
   ahb_rxhwdatam,  
   
   mdi,            
   rstbp,          
   ahb_hwdata,     
   ahb_haddr,      
   ahb_hsel,       
   ahb_htrans,     
   ahb_hwrite,     
   ahb_txhgrant,   
   ahb_rxhgrant,   
   ahb_txhrespm,   
   ahb_rxhrespm,   
   ahb_txhrdatam,  
   ahb_rxhrdatam,  
   ahb_hreadyi,    
   hresetn,        
   hclk,         
   rcg_dut,      
   tcg_dut,      
   tbi_tx_clk,   
   tbi_rx_clk,  
   tx_clk,   
   rx_clk,  
   phyid,
   anx_state
 );

// --------------------------------------------------------------------------
// -- Port Declarations

input   [9:0] tcg_dut;
output  [9:0] rcg_dut;
input         mdc;         
input         mdo;         
input         mdoen;       
input  [31:0] ahb_hrdata;  
input   [1:0] ahb_hresp;   
input         ahb_hreadyo; 
input         ahb_txhbusreq; 
input         ahb_rxhbusreq; 
input   [1:0] ahb_txhtransm; 
input   [1:0] ahb_rxhtransm; 
input  [31:2] ahb_txhaddrm;  
input  [31:2] ahb_rxhaddrm;  
input         ahb_txhwritem; 
input         ahb_rxhwritem; 
input  [31:0] ahb_txhwdatam; 
input  [31:0] ahb_rxhwdatam; 
input  [4:0]  phyid;
input  [9:0]  anx_state;
output        tbi_tx_clk;
output        tbi_rx_clk;
output        tx_clk;
output        rx_clk;
output        mdi;         
output        rstbp;       
output [31:0] ahb_hwdata;  
output  [9:2] ahb_haddr;   
output        ahb_hsel;    
output  [1:0] ahb_htrans;  
output        ahb_hwrite;  
output        ahb_txhgrant;
output        ahb_rxhgrant;
output  [1:0] ahb_txhrespm;
output  [1:0] ahb_rxhrespm;
output [31:0] ahb_txhrdatam;
output [31:0] ahb_rxhrdatam;
output        ahb_hreadyi;
output        hresetn;    
output        hclk;       

// --------------------------------------------------------------------------
// -- Internal Signal Declarations
reg           tbi_tx_clk ; 
reg           tbi_rx_clk ; 
reg           tx_clk ;   
reg           rx_clk ;   
reg           mdi;         
reg           rstbp;       
reg    [31:0] ahb_hwdata;  
reg     [9:2] ahb_haddr;   
reg           ahb_hsel;    
reg     [1:0] ahb_htrans;  
reg           ahb_hwrite;  
reg           ahb_txhgrant;
reg           ahb_rxhgrant;
reg     [1:0] ahb_hrespm;  
reg    [31:0] ahb_hrdatamint;
reg    [31:0] rx_ahb_hrdatamint;
wire          ahb_hreadyi; 
reg           hresetn;     
reg           hclk;        

// ==========================================================================
// == MODULE SIGNALS AND DEFINES
// ==========================================================================

parameter     TP = 1;

integer       hclkprd;       
integer       tbi_tx_clkprd; 
integer       tbi_rx_clkprd; 
integer       tx_clkprd;     
integer       rx_clkprd;     
wire          reset;         

reg    [31:0] ahbram [16'h0100:16'hFFFF]; // AHB RAM model
reg           ahbramen;         // AHB RAM enable
reg           ahb_hwritem_reg;  // AHB RAM write register
reg           rx_ahb_hwritem_reg;  // AHB RAM write register
reg    [17:2] ahb_haddrm_reg;   // AHB RAM write address register
reg    [17:2] rx_ahb_haddrm_reg;   // AHB RAM write address register
reg           tx_ahb_hgranten;     // AHB bus grant enable
reg           rx_ahb_hgranten;     // AHB bus grant enable
reg           ahb_hreadyint;    // AHB ready internal

// ==========================================================================
// == TESTS INVOCATION
// ==========================================================================
assign ahb_txhrespm = 2'b00;
assign ahb_rxhrespm = 2'b00;
initial
begin
   #1 
   resetcore;
   test_anen_en;
   resetcore;
   tbi_loopback_test;
   gl.dsplyend;
   $finish;
end
assign rcg_dut = tcg_dut;

// ==========================================================================
// == TESTS
// ==========================================================================

// ------------------------------------------------------------------------
// Auto-Negotiation Enabled
// TEST SEQUENCE
//    Initialize by restarting auto-negotiation by writing to register. 
//    Verify that Autoneogation was successful. 

task test_anen_en;
reg    [15:0] ii, mgmt_read;
begin
// ------------------------------------------------------------------------
$display(" ---------------------------------------------------------");
$display(" - - - - -TEST CASE : AUTO NEGOTITAION   - - - - - - ");
$display(" ---------------------------------------------------------");
// ------------------------------------------------------------------------
   initregs;
   mstrwr( { 29'h0000_0001, 2'h0 }, 32'h0000_7201); 
   mstrwr( { 29'h0000_0014, 2'h0 }, { 16'h0AAA, 16'h0555} ); 
  repeat(1000)  @ ( posedge tbi_tx_clk );
  $display("\n Auto-Negotiation intiated by CoreTSE_AHB Module");
  $display("\n%0d: Restart Auto Negotiation",$time);
  mgmt_wr( phyid[4:0], 5'h04, 16'h00A0 ); // anar (NP=0 in base page)
  mgmt_wr( phyid[4:0], 5'h11, 16'h4020 ); // sltmr
  mgmt_wr( phyid[4:0], 5'h00, 16'h8140 ); // rstphy,fdx,1000
  mgmt_wr( phyid[4:0], 5'h00, 16'h1340 ); // anen, rstan,fdx,1000

  repeat(3000)  @ ( posedge tbi_tx_clk );

  $display("\n%0d: Verifying Auto-neogation status", $time);
  mgmt_rd( phyid[4:0], 5'h01, mgmt_read );
  if ( mgmt_read[5] !== 1'b1 ) begin
    gl.dsplyerr(" ERROR: Auto-neogation did not Complete");
  end
  if ( mgmt_read[5] == 1'b1 )
    $display("\n%0d: PASS: Auto-neogation Completed",$time);
end
endtask

// --------------------------------------------------------------------------
// -- Random and data, IPG, and preamble pattern tests
task tbi_loopback_test;
  integer     maxfrmbc;                // Maximum frame byte count
  integer     maxfrmcnt;               // Maximum frame count
  integer     maxclklp;                // Maximum number of different hclk period secnarios
  integer   speed;                   // GMII=2, MII100=1, MII10=0
  reg  [31:0] i, j, k, m, r, s;        // variables
  reg [255:0] atfp,   lrfp,   trfp;    // AHB transmit & link receive  descriptors 
  reg [255:0] arfp,   ltfp,   rrfp;    // AHB receive  & link transmit descriptors 
  reg  [31:0] atfpsd;
  reg  [31:0] arfpsd;
  begin
// ------------------------------------------------------------------------
$display(" ---------------------------------------------------------");
$display(" - - - - -TEST CASE : TRANSACTION WITH NEAREND LOOP BACK - - ");
$display(" ---------------------------------------------------------");
// ------------------------------------------------------------------------
    atfp = mlat.dflt_dsc; // initialize AHB transmit descriptor
    lrfp = mllr.dflt_dsc; // initialize link receive descriptor
    arfp = mlar.dflt_dsc; // initialize AHB receive descriptor
    ltfp = mllt.dflt_dsc; // initialize link transmit descriptor
        maxfrmbc  = 128;
        maxfrmcnt = 2;
        maxclklp  = 4;
      for ( k=0; k<maxclklp; k=k+1 ) begin
        hclkprd = mlat.randinrange( 10000, 500, atfpsd );
        $display(" - - -  - - HCLK FREQ %d ps  - - - ",hclkprd);
        for ( speed=2; speed>=0; speed=speed-1 )
        begin
          if ( speed == 2 ) gl.dsplystat(  "Testing GMII speeds.");
          if ( speed == 1 ) gl.dsplystat(  "Testing MII 100 speeds.");
          if ( speed == 0 ) gl.dsplystat(  "Testing MII 10 speeds.");
          if ( speed == 2 ) tx_clkprd = 8000;
          if ( speed == 1 ) tx_clkprd = 40000;
          if ( speed == 0 ) tx_clkprd = 400000;
          if ( speed == 2 ) rx_clkprd = 8000;
          if ( speed == 1 ) rx_clkprd = 40000;
          if ( speed == 0 ) rx_clkprd = 400000;
          resetcore;      
          initregs;
          if ( speed == 1 ) mstrwr( {30'h0E,2'h0}, 32'h02000000 ); // IFCR set M-SGMII speed to 100 Mb/s
          if ( speed == 0 ) mstrwr( {30'h0E,2'h0}, 32'h00000000 ); // IFCR set M-SGMII speed to 100 Mb/s
          if ( speed != 2 ) mstrwr( {30'h01,2'h0}, 32'h00007101 ); // set full duplex and nibble mode in MAC2 reg   
          mstrwr( { 29'h0000_0001, 2'h0 }, {20'h00007,speed[3:0],8'b01} ); // Configuring for GMII, no FCS, no pad, full duplex
          atfpsd = k;
          arfpsd = k;                
          repeat(500) @ ( posedge hclk );
          fork
            //AHB transmit
            begin
            repeat(10) @ ( posedge hclk );
            mstrwr(    32'h0000_0184,   32'h0000_0400 );  // DMA tx descriptor byte address
            mstrwr(    32'h0000_0180,   32'h0000_0001 );  // Enable DMA
            for ( i=0; i< (maxfrmcnt/2); i=i+1 )
            begin
              atfpsd        = $random(atfpsd);
              atfp[191:176] = mlat.randinrange( maxfrmbc, 18, atfpsd ); // set random length
              atfpsd        = $random(atfpsd);
              atfp[199:192] = atfpsd[7:0];                          // set random payload seed
              slvrddesc( 32'h0000_0400, { 32'h0000_1000,            // frame start address
                                          {16'h0000, atfp[191:176] },  // Not empty and a x byte frame
                                          32'h0000_040C });         // Next descriptor start address
              slvrdfrm(  32'h0000_1000,   32'h0000_0400,            // frame data and descriptor address
                                          atfp           );         // build frame descriptor
            $display("          STATUS  : AHB Transmitted %d byte frame",atfp[191:176]);
              atfpsd        = $random(atfpsd);
              atfp[191:176] = mlat.randinrange( maxfrmbc, 18, atfpsd ); // set random length
              atfpsd        = $random(atfpsd);
              atfp[199:192] = atfpsd[7:0];                          // set random payload seed
              slvrddesc( 32'h0000_040C, { 32'h0000_1800,            // frame start address
                                          {16'h0000, atfp[191:176] },  // Not empty and a x byte frame
                                          32'h0000_0400 });         // Next descriptor start address
              slvrdfrm(  32'h0000_1800,   32'h0000_040C,            // frame data and descriptor address
                                          atfp           );         // build frame descriptor
            end
            slvrddesc( 32'h0000_0400, { 32'h0000_1000,               // frame start address
                                        32'h8000_0000,               // Empty and a 0 byte frame
                                        32'h0000_040C });            // Next descriptor start address
            $display("          STATUS  : AHB Transmitted %d byte frame",atfp[191:176]);
          end

          //AHB receieve
          begin
              mstrwr(    32'h0000_0190,   32'h0000_0600  ); // DMA rx descriptor byte address
              mstrwr(    32'h0000_018C,   32'h0000_0001  ); // Enable DMA
              for ( i=0; i<(maxfrmcnt/2); i=i+1 )
              begin
                arfpsd        = $random(arfpsd);
                arfp[191:176] = mlar.randinrange( maxfrmbc, 18, arfpsd ); // set random length
                 
                arfpsd        = $random(arfpsd);
                arfp[199:192] = arfpsd[7:0];                  // set random payload seed
                rxslvrddesc( 32'h0000_0600, { 32'h0000_C000,    // frame start address
                                            32'h8000_0000,    // empty frame flag
                                            32'h0000_060C }); // Next descriptor start address
                slvwrfrm(  32'h0000_C000,   32'h0000_0600,    // frame data and descriptor address
                                            arfp           ); // build frame descriptor
                $display("          STATUS  : AHB  received %d byte frame", arfp[191:176]);
                arfpsd        = $random(arfpsd);
                arfp[191:176] = mlar.randinrange( maxfrmbc, 18, arfpsd ); // set random length
                arfpsd        = $random(arfpsd);
                arfp[199:192] = arfpsd[7:0];                          // set random payload seed
                rxslvrddesc( 32'h0000_060C, { 32'h0000_C800,    // frame start address
                                            32'h8000_0000,    // empty frame flag
                                            32'h0000_0600 }); // Next descriptor start address
                slvwrfrm(  32'h0000_C800,   32'h0000_060C,    // frame data and descriptor address
                                            arfp           ); // build frame descriptor
                $display("          STATUS  : AHB  received %d byte frame", arfp[191:176]);
              end
            end
          join 
  end
end
repeat(500) @ ( posedge hclk );
end
endtask

// ==========================================================================
// == LIBRARY INSTANTIATIONS
// ==========================================================================

gl gl();     // Generic Library instatiations
ml mlat();   // MAC library for AHB transmit
ml mllr();   // MAC library for link receive
ml mllt();   // MAC library for link transmit
ml mlar();   // MAC library for AHB receive

/// =========================================================================
// == MISCELANEOUS
// ==========================================================================
                                                                           
// --------------------------------------------------------------------------
// -- Signal Initialization

initial
begin
   mdi            = 1'b0;
   rstbp          = 1'b0;
   ahb_hwdata     = 32'h0;     
   ahb_haddr      = 8'h0;      
   ahb_hsel       = 1'b0;       
   ahb_htrans     = 2'b00;     
   ahb_hwrite     = 1'b0;     
   ahb_txhgrant     = 1'b0;     
   ahb_rxhgrant     = 1'b0;     
   ahb_hrespm     = 2'b00;      
   ahb_hrdatamint = 32'h0;     
   rx_ahb_hrdatamint = 32'h0;     
   hresetn        = 1'b1;    
   hclk           = 1'b1;       
   tx_clk         = 1'b1;       
   rx_clk         = 1'b1;       

end

// --------------------------------------------------------------------------
// -- Variable Initialization

initial
begin
   hclkprd         = 10000;  // Fabric receive clock period      
   ahbramen        = 1'b0;   // AHB RAM enable
   ahb_hwritem_reg = 1'b0;   // AHB RAM write register
   rx_ahb_hwritem_reg = 1'b0;   // AHB RAM write register
   ahb_haddrm_reg  = 16'h0;  // AHB RAM write address register
   rx_ahb_haddrm_reg  = 16'h0;  // AHB RAM write address register
   tx_ahb_hgranten    = 1'b1;   // AHB bus grant enable
   rx_ahb_hgranten    = 1'b1;   // AHB bus grant enable
   ahb_hreadyint  = 1'b1;   // AHB ready internal
   tbi_tx_clkprd  = 8000;
   tbi_rx_clkprd  = 8000;
   tx_clkprd      = 8000;
   rx_clkprd      = 8000;
end

// --------------------------------------------------------------------------
// -- Logic
assign ahb_hreadyi = ahb_hreadyo & ahb_hreadyint;
always @ ( posedge hclk )
begin
   ahb_txhgrant <= #1 ( ahb_txhbusreq & tx_ahb_hgranten );
end

always @ ( posedge hclk )
begin
   ahb_rxhgrant <= #1 ( ahb_rxhbusreq & rx_ahb_hgranten );
end

// Read AHB RAM
always @ ( posedge hclk )
begin
   if ( ahbramen & ahb_hreadyint )
   begin 
      ahb_hrdatamint <= #1 ahbram[ahb_txhaddrm[17:2]];
   end
end

// Read AHB RAM
always @ ( posedge hclk )
begin
   if ( ahbramen & ahb_hreadyint )
   begin 
      rx_ahb_hrdatamint <= #1 ahbram[ahb_rxhaddrm[17:2]];
   end
end

assign ahb_txhrdatam =   {32{ ahb_hreadyint}} & ahb_hrdatamint     | {32{~ahb_hreadyint}} & 32'hXXXX_XXXX;
assign ahb_rxhrdatam =   {32{ ahb_hreadyint}} & rx_ahb_hrdatamint  | {32{~ahb_hreadyint}} & 32'hXXXX_XXXX;

always @ ( posedge hclk )
begin
   ahb_hwritem_reg <= #1 ahb_txhwritem & ( ahb_txhtransm != 2'b00 );
end


always @ ( posedge hclk )
begin
   rx_ahb_hwritem_reg <= #1 ahb_rxhwritem & ( ahb_rxhtransm != 2'b00 );
end


always @ ( posedge hclk )
begin
   ahb_haddrm_reg  <= #1 ahb_txhaddrm[17:2];
end

always @ ( posedge hclk )
begin
   rx_ahb_haddrm_reg  <= #1 ahb_rxhaddrm[17:2];
end

// Write AHB RAM
always @ ( posedge hclk )
begin
   if ( ahb_hwritem_reg )
   begin
      ahbram[ahb_haddrm_reg[17:2]] <= #1 ahb_txhwdatam;
   end
end


// Write AHB RAM
always @ ( posedge hclk )
begin
   if ( rx_ahb_hwritem_reg )
   begin
      ahbram[rx_ahb_haddrm_reg[17:2]] <= #1 ahb_rxhwdatam;
   end
end

always
begin
 tx_clk = #(tx_clkprd/2) 1'b0 ; 
 tx_clk = #(tx_clkprd/2) 1'b1 ; 
end

always
begin
 rx_clk = #(rx_clkprd/2) 1'b0 ; 
 rx_clk = #(rx_clkprd/2) 1'b1 ; 
end

always
begin
 tbi_tx_clk = #(tbi_tx_clkprd/2) 1'b0 ; 
 tbi_tx_clk = #(tbi_tx_clkprd/2) 1'b1 ; 
end

always
begin
 tbi_rx_clk = #(tbi_rx_clkprd/2) 1'b0 ; 
 tbi_rx_clk = #(tbi_rx_clkprd/2) 1'b1 ; 
end

always 
begin
   hclk = #(hclkprd/2)  1'b0;
   hclk = #(hclkprd/2)  1'b1;
end

// --------------------------------------------------------------------------
// -- Reset mac ahb
assign reset = ~hresetn;
task resetcore;
begin                                                             
   repeat(20)  @(posedge hclk );
   gl.dsplystat("Hard reseting mac ahb.");
   hresetn    = 1'b1;
   repeat(20)  @(posedge hclk );
   hresetn    = 1'b0;
   repeat(20)  @(posedge hclk );
   hresetn    = 1'b1;
   repeat(100) @(posedge hclk )  #1;
end                           
endtask
// ------------------------------------------------------------------------
// task: mgmt_wr
//
// performs a MII Mgmt Write Cycle
task mgmt_wr;
input [4:0]  phyadr, regadr;
input [15:0] control;
begin
 mstrwr( {8'h0A,2'h0}, {19'h0,phyid[4:0],3'b0,regadr} );
 mstrwr( {8'h0B,2'h0}, {16'h0,control} );
 repeat(100)  @ ( posedge mdc );

end
endtask

// ------------------------------------------------------------------------
// task: mgmt_rd
//
// performs a MII Mgmt Read Cycle
task mgmt_rd;
input [4:0]  phyadr, regadr;
output [15:0] status;
begin
 mstrwr( {8'h0A,2'h0}, {19'h0,phyid[4:0],3'b0,regadr} );
 mstrwr( {8'h09,2'h0}, {30'h0,1'b1} );
 repeat(100)  @ ( posedge mdc );
 mstrrd( 8'h0C,status);
end
endtask

// --------------------------------------------------------------------------
// -- AHB master write to M-AHBE                                            ///// AHB SLAVE na register AHB MASTER thi config karaviya 6e
task mstrwr;
   input [31:0] adx;             // Frame discriptor
   input [31:0] idat;            // Interface descriptor
begin
   while ( ~ahb_hreadyo ) @ ( posedge hclk | ahb_txhgrant | ahb_rxhgrant) #1;
   ahb_hsel   = 1'b1;
   ahb_htrans = 2'b10; // nonseq
   ahb_haddr  = adx[31:2];
   ahb_hwrite = 1'b1;
   @ ( posedge hclk ) #1;
   ahb_hsel   = 1'b0;
   ahb_haddr  = 30'h0000_0000;
   ahb_hwdata = idat;
   @ ( posedge hclk )
   while ( ~ahb_hreadyo ) @ ( posedge hclk );
   if ( ahb_hresp !== 2'b00 ) // not equal to okay
      gl.dsplycmperr( "ahb_hrespm", 2'b00, ahb_hresp ); 
end
endtask

// --------------------------------------------------------------------------
// -- AHB read from M-AHBE
task mstrrd;
   input [31:0] adx;             // Frame discriptor
   output [31:0] idat;            // Interface descriptor
begin
   while ( ~ahb_hreadyo ) @ ( posedge hclk | ahb_txhgrant | ahb_rxhgrant) #1;
   ahb_hsel   = 1'b1;
   ahb_htrans = 2'b10; // nonseq
   ahb_haddr  = adx[31:2];
   ahb_hwrite = 1'b0;
   @ ( posedge hclk ) #1;
   while ( ~ahb_hreadyo ) @ ( posedge hclk );
   #1;
   ahb_hsel   = 1'b0;
   ahb_haddr  = 30'h0000_0000;
   idat = ahb_hrdata;
end
endtask

task test_reg_wr_rd;
    reg [31:0] data;
    reg [31:0] data_rd;
begin
   data = 32'h1234_dead;
   data_rd = 32'h0;
   mstrwr( { 29'h0000_0019, 2'h0 }, data);  // AMCXFIF cfg 3
   mstrrd( { 29'h0000_0019, 2'h0 },data_rd);
   $display("rd data 0x%x ",data_rd);
end
endtask

// --------------------------------------------------------------------------
// -- Initialize fif registers to baseline
task initregs;
begin
    //test_reg_wr_rd;
   mstrwr( { 29'h0000_0000, 2'h0 }, 32'h0000_0005 ); // MAC1   
   mstrwr( { 29'h0000_0001, 2'h0 }, 32'h0000_7000 ); // MAC2   
   mstrwr( { 29'h0000_0002, 2'h0 }, 32'h4060_5060 ); // IPGT   
   mstrwr( { 29'h0000_0003, 2'h0 }, 32'h00a1_f037 ); // HFDP
   mstrwr( { 29'h0000_0004, 2'h0 }, 32'h0000_0600 ); // MAXF
   mstrwr( { 29'h0000_0010, 2'h0 }, 32'hA5A4_A3A2 ); // SA0
   mstrwr( { 29'h0000_0011, 2'h0 }, 32'hA1A0_0000 ); // SA1
   mstrwr( { 29'h0000_0012, 2'h0 }, { 16'h00, 8'hFF, 8'h0 } ); // AMCXFIF cfg 0
   mstrwr( { 29'h0000_0015, 2'h0 }, { 16'd1664, 16'hFFFF } );  // AMCXFIF cfg 3
end
endtask

// --------------------------------------------------------------------------
// -- M-AHBE reading descriptor from slave (RAM)          // ae task ae data ram ma data read kariyo
task slvrddesc;
   input   [31:0] descadx;           // Frame discriptor RAM address
   input   [95:0] descdat;           // RAM data
   integer        slvrddesc_prb;     // slvrddesc task probe
begin
   while ( ~ahb_txhbusreq )                             @ ( posedge hclk );
   while ( ~((ahb_txhtransm == 2'h2 ) & ~ahb_txhwritem) ) @ ( posedge hclk );
   #1;
   ahb_hrdatamint = descdat[95:64];
   @ ( posedge hclk );
   #1;
   ahb_hrdatamint = descdat[63:32];
   @ ( posedge hclk );
   #1;
   ahb_hrdatamint = descdat[31:0];
end
endtask


// --------------------------------------------------------------------------
// -- M-AHBE reading descriptor from slave (RAM)          // ae task ae data ram ma data read kariyo
task rxslvrddesc;
   input   [31:0] descadx;           // Frame discriptor RAM address
   input   [95:0] descdat;           // RAM data
   integer        slvrddesc_prb;     // slvrddesc task probe
begin
   while ( ~ahb_rxhbusreq )                             @ ( posedge hclk );
   while ( ~((ahb_rxhtransm == 2'h2 ) & ~ahb_rxhwritem) ) @ ( posedge hclk );
   #1;
   rx_ahb_hrdatamint = descdat[95:64];
   @ ( posedge hclk );
   #1;
   rx_ahb_hrdatamint = descdat[63:32];
   @ ( posedge hclk );
   #1;
   rx_ahb_hrdatamint = descdat[31:0];
end
endtask


// --------------------------------------------------------------------------
// -- M-AHBE reading frame from slave (RAM)             ///  ae task ae data ne ram mathi read karsh
task slvrdfrm;
   input   [31:0] frmadx;            // Frame data RAM address
   input   [31:0] dscadx;            // Frame descriptor RAM address
   input  [255:0] bldfrmdesc;        // build frame descriptor
   integer        curbc;             // Current byte count transmitted
   integer        trmbc;             // Terminal byte count transmitted
   integer        slvrdfrm_prb;      // slvrdfrm task probe
begin
   trmbc = mlat.bld_frm(bldfrmdesc);
   @ ( posedge hclk );
   while ( ~ahb_txhbusreq )                             @ ( posedge hclk );
   while ( ~(( ahb_txhtransm == 2'h2 ) & ~ahb_txhwritem & ( frmadx[31:2] == ahb_txhaddrm )) )
      @ ( posedge hclk );
   curbc = 0;
   while ( curbc < trmbc )
   begin
      # 1;                                            
      ahb_hrdatamint <= { mlat.bld_frm_mem[curbc+3], 
                          mlat.bld_frm_mem[curbc+2], 
                          mlat.bld_frm_mem[curbc+1], 
                          mlat.bld_frm_mem[curbc]    };
      curbc    = curbc + 4;
      @ ( posedge hclk );
   end
   if ( ~ahb_txhwritem ) 
      gl.dsplycmperr( "ahb_hwritem", 1'b1, ahb_txhwritem ); 
   if ( ahb_txhaddrm  !== ( dscadx[31:2] + 1'b1 )) 
      gl.dsplycmperr( "ahb_haddrm", ( dscadx[31:2] + 1'b1 ), ahb_txhaddrm ); 
end
endtask

// --------------------------------------------------------------------------
// -- M-AHBE write frame to slave (RAM)
task slvwrfrm;
   input   [31:0] frmadx;            // Frame data RAM address
   input   [31:0] dscadx;            // Frame descriptor RAM address
   input  [255:0] bldfrmdesc;        // build frame descriptor
   integer        curbc;             // Current byte count transmitted
   integer        trmbc;             // Terminal byte count transmitted
   reg     [31:0] hwdata_exp;
   integer        slvwrfrm_prb;      // slvwrfrm task probe
begin
   trmbc = mlar.bld_frm(bldfrmdesc);
   @ ( posedge hclk );
   while ( ~ahb_rxhbusreq ) @ ( posedge hclk );
   while ( ~((ahb_rxhtransm == 2'h2 ) & ahb_rxhwritem & ( frmadx[31:2]     == ahb_rxhaddrm ) ) ) 
      @ ( posedge hclk );
   @ ( posedge hclk );
   while ( ~((ahb_rxhtransm == 2'h3 ) & ahb_rxhwritem & ( (frmadx[31:2]+1) == ahb_rxhaddrm ) ) ) 
      @ ( posedge hclk );
   curbc = 0;
   while ( curbc < trmbc )
   begin
      hwdata_exp = { mlar.bld_frm_mem[curbc+3], 
                     mlar.bld_frm_mem[curbc+2], 
                     mlar.bld_frm_mem[curbc+1], 
                     mlar.bld_frm_mem[curbc]    };
      if ( ((curbc + 4 ) > trmbc ) & (( trmbc % 4 ) == 1 ) )
      begin
         if ( ahb_rxhwdatam[ 7:0] !== hwdata_exp[ 7:0] )
            gl.dsplycmperr( "ahb_hwdatam", { 24'hXXXXXX, hwdata_exp[7:0]  }, ahb_rxhwdatam );
      end
      else if ( (( curbc + 4 ) > trmbc )  & (( trmbc % 4 ) == 2 ) )
      begin
         if ( ahb_rxhwdatam[15:0] !== hwdata_exp[15:0] )
            gl.dsplycmperr( "ahb_hwdatam", { 16'hXXXX,   hwdata_exp[15:0] }, ahb_rxhwdatam );
      end
      else if ( (( curbc + 4 ) > trmbc )  & (( trmbc % 4 ) == 3 ) )
      begin
         if ( ahb_rxhwdatam[23:0] !== hwdata_exp[23:0] )
            gl.dsplycmperr( "ahb_hwdatam", { 8'hXX,      hwdata_exp[23:0] }, ahb_rxhwdatam );
      end
      else if ( ahb_rxhwdatam[31:0] !== hwdata_exp[31:0] )begin
         gl.dsplycmperr( "ahb_hwdatam",               hwdata_exp[31:0]  , ahb_rxhwdatam );
       end
      curbc = curbc + 14'h0004;
      @ ( posedge hclk );
      if ( (curbc > trmbc ) & ( ahb_rxhwdatam[31:0] !== trmbc ) )     
         gl.dsplycmperr( "RX descriptor byte cont", trmbc, ahb_rxhwdatam );
   end
end
endtask
endmodule

module gl;
// --------------------------------------------------------------------------
// -- GLOBAL SIGNALS AND DEFINES
`define      DSPLYVRBS 1    // Define Runtime terminal display reporting verbose
`define      MFC       0   // Define maximum falure count. 0 = infinite
reg   [31:0] glb_fc;        // Global variable failure count
real         glb_tnum;      // Global variable test number active

task dsplyend;
begin
   if ( glb_fc !== 0 )
   begin
      $display(" ");
      $display("// ------------------------------------------------------------------------ //");
      $display("//                   ----        -         ---      -                       //");
      $display("//                   -          - -         -       -                       //");
      $display("//                   ---       -----        -       -                       //");
      $display("//                   -        -     -       -       -                       //");
      $display("//                   -       -       -     ---      ------                  //");
      $display("// ------------------------------------------------------------------------ //");
   end
   else
   begin
      $display(" ");
      $display("// ------------------------------------------------------------------------ //");
      $display("//                   ++++        +         ++++      ++++                   //");
      $display("//                   +   +      + +       +         +                       //");
      $display("//                   ++++      +++++       ++++      ++++                   //");
      $display("//                   +        +     +          +         +                  //");
      $display("//                   +       +       +     ++++      ++++                   //");
      $display("// ------------------------------------------------------------------------ //");
   end
end                                                                                      
endtask

task dsplystat;
   input [8*120:1] stattxt;
begin
   if ( `DSPLYVRBS >= 1 )
      $display("          STATUS  : %0s", stattxt);
end
endtask

task dsplyerr;
   input [8*120:1] toerrtxt;
begin                              
   $display("   ERROR   : %0s", toerrtxt ); 
   glb_fc = glb_fc + 1; 
end
endtask

task dsplycmperr;
   input [8*120:1] cmperrsig;
   input    [71:0] cmperrxpt;
   input    [71:0] cmperract;
begin
   $display("   ERROR   : Data miscompare on signal %0s, at time %0d.", cmperrsig, $time);
   $display("             Expected value = %h,  Actual value = %h.", cmperrxpt, cmperract); 
   glb_fc = glb_fc + 1; 
end
endtask

// -- Global Variable Initialization
initial 
begin
   glb_fc   = 0;
end

// --------------------------------------------------------------------------
// -- Simulation termination due to maximum failure count reached
always @ ( glb_fc )
begin
   if (( `MFC <= glb_fc ) & ( `MFC !== 0 ))
   begin
      #1;
      dsplystat( "Maximum testbench Error count exceeded.");
      dsplystat( "Simulation terminated prematurely");
      dsplyend;
      #1;
      $finish;
   end
   #1; 
end
endmodule

module ml;
// --------------------------------------------------------------------------
// -- GLOBAL SIGNALS AND DEFINES
reg    [7:0] bld_frm_mem  [0:35535]; // build frame task global memory
 
// --------------------------------------------------------------------------
// --- Default descriptor constant 
parameter dflt_dsc = {
      20'd0,                // unused     255 : 236
       1'b0,                // car_snse   235       // carrier sense
       1'b0,                // cf         234       // generic control frame
       1'b0,                // dat_evnt   233       // A data event occured since last packet
       1'b0,                // abrt       232       // trunc is due to abort
      16'd1536,             // truncbc    231 : 216 // 16'hFFFF is no trunc
       1'b0,                // pad_68     215        
       1'b0,                // pad_64     214
       1'b0,                // rmvfcs     213       // frame 4 bytes shorter than LEN
       1'b0,                // pf         212       // pause control frame
       2'b00,               // dlyfcs     211 : 210
       1'b0,                // drop       209
       1'b0,                // badfrm     208
       1'b0,                // coderr     207
       1'b1,                // check      206       // RSV length checking enabled
       1'b0,                // endian     205
       1'b0,                // nofcs      204       // frame length equal to LEN
       1'b0,                // zfcs       203
       1'b0,                // fcserr     202       // create ranbom bit error in FCS
       1'b0,                // tagged     201
       1'b0,                // dix        200       // force [143:128] to L/T field
       8'h01,               // pattern    199 : 192
      16'd64,               // totlenreq  191 : 176
      32'h0,                // fill       175 : 144
      16'h0,                // etype      143 : 128
      32'h8100_abcd,        // vlan tag   127 : 96  (make non-zero for stats)
      48'h5051_5253_5455,   // sa         95  : 48
      48'hd0d1_d2d3_d4d5 }; // da         47  : 0

// --------------------------------------------------------------------------
// --- Writes descriptor defined data pattern into bld_frm_mem
function [31:0] bld_frm;
//task bld_frm;
   input [255:0] fp;           // frame parameter
   reg    [47:0] macda;        // 48-bit destination MAC address
   reg    [47:0] macsa;        // 48-bit source MAC address
   reg    [31:0] tag;          // 32-bit VLAN tag {vlan_etype, pri, tr, VLAN}
   reg    [15:0] etype;        // 16-bit ethernet type
   reg    [15:0] totlenreq;    // requested Total Length of frame in bytes
   reg    [15:0] totlen;       // calculated actual Total Length of frame in bytes
   reg     [7:0] pattern;      // 8-bit data Pattern specifier: 01=count up,
                               //      - 02=count down, else random data
   reg           dix;          // 1=etype in Etype/Len field, 0=LEN
   reg           tagged;       // frame is tagged, use tag
   reg           fcserr;       // FCS error
   reg           zfcs;         // zero-out frame's FCS
   reg           nofcs;        // No FCS at end of frame (SOF qualifier is 3)
   reg           rmvfcs;       // No FCS at end of frame frame shorter by 4 bytes
   reg           coderr;       // code error
   reg     [1:0] dlyfcs;       // delayed FCS, 0=none, 1=4 bytes, 2=8 bytes
   reg           pf;           // pause control frame
   reg           cf;           // generaic control frame
   reg           endian;
   reg           badfrm;
   reg           pad_68;
   reg    [15:0] fcs_start;    // FCS calculation start offset
   reg    [15:0] load_start;   // payload start offset
   reg    [15:0] load_end;     // payload end
   reg    [31:0] seed;         // scratch random number seed
   reg    [31:0] crc, crc_out; // scratch crc data words
   reg    [15:0] len;          // scratch frame length
   reg           drop;         // Will not be passed
   reg           pad_64;       // pad to 64 bytes
   integer       j, k;         // scratch counters
begin
   // Illegal conditions
   if ( ^fp === 1'bX )
   begin
      $display( "ERROR: Illegal input condition in %m function : ( ^fp === 1'bX )");
      $stop;
   end
   pf = fp[212];
   cf = fp[234];
   if ( pf | cf )
   begin
      macda     = 48'h0180_c200_0001;
      macsa     = fp[95:48];
      if   ( pf ) tag        = 32'h8808_0001;
      else        tag[31:16] = 16'h8808;
      etype     = fp[143:128]; // pause timer value
      totlenreq = 16'h0040;
      pattern   = 8'h00;
      dix       = 1'b1;
      tagged    = 1'b1;
      rmvfcs    = fp[213];
      {fcserr,  zfcs, nofcs, coderr, dlyfcs} = 6'h00;
   end
   else begin
      macda     = fp[47:0];
      macsa     = fp[95:48];
      tag       = fp[127:96];
      etype     = fp[143:128];
      totlenreq = fp[191:176];    
      pattern   = fp[199:192];
      dix       = fp[200];
      tagged    = fp[201];
      fcserr    = fp[202];
      zfcs      = fp[203];
      nofcs     = fp[204];
      endian    = fp[205];
      coderr    = fp[207];
      badfrm    = fp[208];
      drop      = fp[209];
      dlyfcs    = fp[211:210];
      rmvfcs    = fp[213];
      pad_64    = fp[214];
      pad_68    = fp[215];       
   end
   if ( nofcs & rmvfcs )
   begin
      $display( "ERROR: Illegal input condition in %m function : ( nofcs & rmvfcs )");
      $stop;
   end
   seed = pattern;
   seed = $random(seed);
   // Calculate actual total length from requested
   if      ( pad_68 & ( totlenreq < 68 ))  totlen = 68;
   else if ( pad_64 & ( totlenreq < 64 ))  totlen = 64;
   else if ( rmvfcs & ( totlenreq >  4 ))  totlen = totlenreq - 4;
   else                                    totlen = totlenreq;
   // Add known pattern for packet header if delayed FCS is used
   j=0;
   if ( dlyfcs > 2'b00 )
   begin
      if(`DSPLYVRBS>1) $display( "  %m Adding header word 1 = dead" );
      bld_frm_mem[j] = 8'hde;       j=j+1;
      bld_frm_mem[j] = 8'had;       j=j+1;
      bld_frm_mem[j] = 8'hde;       j=j+1;
      bld_frm_mem[j] = 8'had;       j=j+1;
   end
   if ( dlyfcs > 2'b01 )
   begin
      if(`DSPLYVRBS>1) $display( "  %m Adding header word 2 = beef" );
      bld_frm_mem[j] = 8'hbe;       j=j+1;
      bld_frm_mem[j] = 8'hef;       j=j+1;
      bld_frm_mem[j] = 8'hbe;       j=j+1;
      bld_frm_mem[j] = 8'hef;       j=j+1;
   end
   if ( dlyfcs > 2'b10 )
   begin
      if(`DSPLYVRBS>1) $display( "  %m Adding header word 3 = cafe" );
      bld_frm_mem[j] = 8'hca;       j=j+1;
      bld_frm_mem[j] = 8'hfe;       j=j+1;
      bld_frm_mem[j] = 8'hca;       j=j+1;
      bld_frm_mem[j] = 8'hfe;       j=j+1;
   end
   // Add MAC addresses to frame memory
   if(`DSPLYVRBS>1) $display( "  %m Adding MAC DA = %h", macda );
   bld_frm_mem[j] = macda[47:40];   j=j+1;
   bld_frm_mem[j] = macda[39:32];   j=j+1;
   bld_frm_mem[j] = macda[31:24];   j=j+1;
   bld_frm_mem[j] = macda[23:16];   j=j+1;
   bld_frm_mem[j] = macda[15:8];    j=j+1;
   bld_frm_mem[j] = macda[7:0];     j=j+1;
   if(`DSPLYVRBS>1) $display( "  %m Adding MAC SA = %h", macsa );
   bld_frm_mem[j] = macsa[47:40];   j=j+1;
   bld_frm_mem[j] = macsa[39:32];   j=j+1;
   bld_frm_mem[j] = macsa[31:24];   j=j+1;
   bld_frm_mem[j] = macsa[23:16];   j=j+1;
   bld_frm_mem[j] = macsa[15:8];    j=j+1;
   bld_frm_mem[j] = macsa[7:0];     j=j+1;
   // Add tag to frame memory
   if ( tagged )
   begin
      if(`DSPLYVRBS>1) $display( "  %m building tag with %h_%h", tag[31:16], tag[15:0] );
      bld_frm_mem[j] = tag[31:24];  j=j+1;
      bld_frm_mem[j] = tag[23:16];  j=j+1;
      bld_frm_mem[j] = tag[15:8];   j=j+1;
      bld_frm_mem[j] = tag[7:0];    j=j+1;
   end
   // Add Etype/Len to frame memory
   if ( dix )
   begin
      if(`DSPLYVRBS>1) $display( "  %m Adding ETYPE %h", etype );
      bld_frm_mem[j] = etype[15:8]; j=j+1;
      bld_frm_mem[j] = etype[7:0];  j=j+1;
   end
   else begin
   // Subtract SA, DA, Len/type, FCS, prepend
      if ( totlenreq > 18 + dlyfcs*4 ) len = totlenreq - 18 - dlyfcs*4;
      else                          len = 0;
      if ( tagged & len > 2 ) len = len - 4;
      if(`DSPLYVRBS>1) $display( "  %m Adding LEN %h", len );
      bld_frm_mem[j] = len[15:8];   j=j+1;
      bld_frm_mem[j] = len[7:0];    j=j+1;
   end
   // Add payload data to temporary memory
   load_start = j;
   if   ( nofcs ) load_end = totlenreq;
   else           load_end = totlenreq - 4;
   for ( j=load_start; j<load_end; j=j+1 )
   begin
    // $display("load_start = %d load_end = %d ",load_start,load_end);

      case ( pattern )
         0:                        bld_frm_mem[j] = 8'h00;  
         1: begin                                  // Count up
            if ( j == load_start ) bld_frm_mem[j] = 8'h00;
            else                   bld_frm_mem[j] = bld_frm_mem[j-1] + 8'h01;
         end
         2: begin                                  // Count down
            if ( j == load_start ) bld_frm_mem[j] = 8'hFF;
            else                   bld_frm_mem[j] = bld_frm_mem[j-1] - 8'h01;
         end
         default: 
         begin
            seed = $random( seed );
            bld_frm_mem[j] = seed[7:0];                          
          end
      endcase
   end
   // Add pad optionaly
   while ( ( pad_64 & ( j < 60 ) ) | ( pad_68 & ( j < 64 ) ) )
   begin
      bld_frm_mem[j] = 8'h00;
      j = j + 1;
   end
   // Generate 32-bit CRC
   if ( ~nofcs & ~rmvfcs )            
   begin  
       if ( totlen > 7 )
       begin
         if ( zfcs ) crc = 32'h0000_0000;
         else begin
            crc = 32'hFFFF_FFFF;                        // Start with all F's
            if      ( dlyfcs == 2'b00 ) fcs_start = 16'h0000;
            else if ( dlyfcs == 2'b01 ) fcs_start = 16'h0004;
            else if ( dlyfcs == 2'b10 ) fcs_start = 16'h0008;
            else                        fcs_start = 16'h000c;
            for ( j=fcs_start; j < totlen - 4; j=j+1 )
            begin
               crc = crc_gen_32( crc, bld_frm_mem[j] );
            end
            crc = ~crc;                                 // Invert result
            if ( fcserr ) crc[seed[4:0]] = ~crc[seed[4:0]];
            crc = {crc[24], crc[25], crc[26], crc[27],  // Reverse bit order
                   crc[28], crc[29], crc[30], crc[31],
                   crc[16], crc[17], crc[18], crc[19],
                   crc[20], crc[21], crc[22], crc[23],
                   crc[8],  crc[9],  crc[10], crc[11],
                   crc[12], crc[13], crc[14], crc[15],
                   crc[0],  crc[1],  crc[2],  crc[3],
                   crc[4],  crc[5],  crc[6],  crc[7]};
         end
         if(`DSPLYVRBS>1) $display( "  %m, crc=%h", crc );
         // Add CRC to temporary memory, MSB first
         j = totlen - 4;
         bld_frm_mem[j] = crc[31:24]; j=j+1;
         bld_frm_mem[j] = crc[23:16]; j=j+1;
         bld_frm_mem[j] = crc[15:8];  j=j+1;
         bld_frm_mem[j] = crc[7:0];   j=j+1;
      end
   end
   // Perform truncation if necessary
   if (( fp[231:216] < totlen ) & ~(&fp[231:216]) ) totlen = fp[231:216];
   bld_frm = totlen;
end
endfunction

// --------------------------------------------------------------------------
// -- Generates 32 bit CRC from 8 bit input and previous 32 bit CRC
function [31:0] crc_gen_32;
   input    [31:0] crc;
   input     [7:0] d;
   reg      [31:0] o_crc;
begin
   o_crc[31] = crc[29]^d[2] ^ crc[23];
   o_crc[30] = crc[31]^d[0] ^ crc[28]^d[3] ^ crc[22];
   o_crc[29] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[27]^d[4] ^ crc[21];
   o_crc[28] = crc[30]^d[1] ^ crc[29]^d[2] ^ crc[26]^d[5] ^ crc[20];
   o_crc[27] = crc[31]^d[0] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[25]^d[6] ^ crc[19];
   o_crc[26] = crc[30]^d[1] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[24]^d[7] ^ crc[18];
   o_crc[25] = crc[27]^d[4] ^ crc[26]^d[5] ^ crc[17];
   o_crc[24] = crc[31]^d[0] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[16];
   o_crc[23] = crc[30]^d[1] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[15];
   o_crc[22] = crc[24]^d[7] ^ crc[14];
   o_crc[21] = crc[29]^d[2] ^ crc[13];
   o_crc[20] = crc[28]^d[3] ^ crc[12];
   o_crc[19] = crc[31]^d[0] ^ crc[27]^d[4] ^ crc[11];
   o_crc[18] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[26]^d[5] ^ crc[10];
   o_crc[17] = crc[30]^d[1] ^ crc[29]^d[2] ^ crc[25]^d[6] ^ crc[9];
   o_crc[16] = crc[29]^d[2] ^ crc[28]^d[3] ^ crc[24]^d[7] ^ crc[8];
   o_crc[15] = crc[31]^d[0] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[7];
   o_crc[14] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[6];
   o_crc[13] = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[29]^d[2] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[5];
   o_crc[12] = crc[30]^d[1] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[4];
   o_crc[11] = crc[28]^d[3] ^ crc[27]^d[4] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[3];
   o_crc[10] = crc[29]^d[2] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[24]^d[7] ^ crc[2];
   o_crc[9]  = crc[29]^d[2] ^ crc[28]^d[3] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[1];
   o_crc[8]  = crc[28]^d[3] ^ crc[27]^d[4] ^ crc[25]^d[6] ^ crc[24]^d[7] ^ crc[0];
   o_crc[7]  = crc[31]^d[0] ^ crc[29]^d[2] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[24]^d[7];
   o_crc[6]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[26]^d[5] ^ crc[25]^d[6];
   o_crc[5]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[29]^d[2] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[25]^d[6] ^ crc[24]^d[7];
   o_crc[4]  = crc[30]^d[1] ^ crc[28]^d[3] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[24]^d[7];
   o_crc[3]  = crc[31]^d[0] ^ crc[27]^d[4] ^ crc[26]^d[5] ^ crc[25]^d[6];
   o_crc[2]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[26]^d[5] ^ crc[25]^d[6] ^ crc[24]^d[7];
   o_crc[1]  = crc[31]^d[0] ^ crc[30]^d[1] ^ crc[25]^d[6] ^ crc[24]^d[7];
   o_crc[0]  = crc[30]^d[1] ^ crc[24]^d[7];
   crc_gen_32 = o_crc;
end
endfunction

   
// --------------------------------------------------------------------------
// -- Returns random between and including maximum and minimum values
function [31:0] randinrange;
   input [31:0] max;
   input [31:0] min;
   input [31:0] seed;
begin
   randinrange = ({$random(seed)} % ((max-min) + 1 )) + min;
end
endfunction
endmodule
