`timescale 1ns / 1ps

`include "src/eth/eth_mac.v"

module eth_mac_test;

	// Inputs
	reg clk;
	reg rst;
	reg clear;
	wire [7:0] mem_data;
	reg [31:0] ctrl_word;

	// Outputs
	wire [11:0] mem_addr;
	wire TXEN;
	wire [1:0] TXD;

	// Instantiate the Unit Under Test (UUT)
	eth_mac uut (
		.clk(clk), 
		.rst(rst), 
		.clear(clear), 
		.mem_data(mem_data), 
		.mem_addr(mem_addr), 
		.ctrl_word(ctrl_word), 
		.TXEN(TXEN), 
		.TXD(TXD)
	);
	
	always #10 clk <= ~clk;
	reg run;

	// memory
	localparam MEM_SIZE = 445;
	reg [7:0] mem [0:MEM_SIZE-1]; 
	assign mem_data = mem[mem_addr];
	
	// frame data
	localparam FRAME_ADDR = 0;
	localparam FRAME_LENGTH = 10;
	localparam START = (1 << 31);
	
	// RMII deserializer
	integer wrt_cntr;
	reg [7:0] deser;
	always @(posedge clk)
	begin
		if (TXEN && run)
		begin
			deser = {TXD, deser[7:2]}; // right shift
			wrt_cntr = wrt_cntr + 1;
			if ((wrt_cntr & 32'b11) == 0)
			begin
				//$fwrite(ofile, "%c", deser);
				$display("%c", deser);
			end
		end
	end
	
	initial begin
		// Initialize Inputs
		clk <= 0;
		rst <= 1;
		clear <= 0;
		ctrl_word <= 0;

		deser = 0;
		wrt_cntr = 0;
		run <= 0;

		// populate memory
		$readmemh("src/sim/eth_large_frame_mem.mem", mem);

		// Wait 20 ns for global reset to finish
		#20;
      	rst <= 0;
		  
		// Add stimulus here
		#20;
		@(posedge clk);
		
		ctrl_word <= START | (FRAME_LENGTH << 12) | (FRAME_ADDR);
		run <= 1;
		
		@(TXEN == 1);
		
		ctrl_word <= 0;
		
		@(TXEN == 0);
		
		#20;
		
		$finish;
	end
      
endmodule

