`timescale 1ns / 1ps

`include "src/fifo.v"

module fifo_test;
	// Inputs
	reg clk;
	reg rst;
	reg clear;
	reg [7:0] in;
	reg push;
	reg pop;

	// Outputs
	wire [7:0] out;
	wire empty;
	wire out_valid;
	wire full;

	// Instantiate the Unit Under Test (UUT)
	fifo uut (
		.clk(clk), 
		.rst(rst), 
		.clear(clear), 
		.in(in), 
		.push(push), 
		.out(out), 
		.pop(pop), 
		.empty(empty), 
		.out_valid(out_valid), 
		.full(full)
	);

	always #10 clk = ~clk;
	
	always @(posedge clk)
	begin
		if (c >= 0 && !rst)
		begin
			pop <= $random & 1'b1;
			push <= $random & 1'b1;
		end
		else
		begin
			push <= 0;
		end
	end

	always @(posedge clk)
	begin
		if (out_valid)
		begin
			$display("%c", out);
			//$fdisplay(ofile, "%c", out);
			$fwrite(ofile, "%c", out);
		end
	end
	
	always @(posedge clk)
	begin
		if ((!full && push) || start)
		begin
			c = $fgetc(ifile);
			if (c != -1)
			begin
				in <= c[7:0];
			end
		end
		start <= 0;
	end
	
	integer ifile, ofile, c;
	reg start;

	initial begin
		// Initialize Inputs
		clk <= 0;
		rst <= 1;
		clear <= 0;
		in <= 0;
		pop <= 0;
		push <= 0;
		
		c = 0;
		start <= 0;
		
		// Wait 20ns for global reset to finish
		#20;
		rst <= 0;
        
		// Add stimulus here
		
		// open file holding the test input
		ifile = $fopen("src/sim/lorem_ipsum.txt", "r");
		ofile = $fopen("src/sim/fifo_out.txt", "w");
		if ((ifile == 0) || (ofile == 0))
		begin
			$display("Error on opening at least one of the files!\n");
			$finish;
		end
		
		// start simulation
		start <= 1;
		
		// wait until EOF is reached
		@(c == -1);
		
		// wait for FIFO depletion
		if (!empty)
		begin
			@(posedge empty);
		end
		
		$fclose(ifile);
		$fclose(ofile);
		$finish;
		
	end
      
endmodule

