`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    11:33:43 09/05/2007 
// Design Name: 
// Module Name:    serial_iface 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

`include "defines.v"

module serial_iface(

	uartclk_i, clk_i, reset_i, addr_i, data_i,
	data_o, Breq_i, WR_i, reqp_o,
	Brdy_o, RX, TX);

	input uartclk_i;
	input clk_i;
	input reset_i;
	input [31:0] addr_i;
	input [31:0] data_i;
	output [31:0] data_o;
	input Breq_i;
	input WR_i;
	output reqp_o;
	output Brdy_o;
	input RX;
	output TX;
	
	wire [29:0] uart_addr;
	wire uart_reqp;
	wire uart_brdy;
	wire [31:0] uart_dout;
	wire myreq;
	reg [1:0] bstate;
	
	parameter ba= `UART_BASE_ADDR;
	parameter dev_id = `UART_DEV_ID;
	
	parameter bs_idle   = 2'b00;
	parameter bs_wait   = 2'b01;
	parameter bs_next   = 2'b10;
	
	
	always @(posedge clk_i) begin
		if (reset_i)
			bstate <= bs_idle;
		else begin
			case (bstate)
			
				bs_idle:
					if (myreq)
						bstate <= bs_wait;
				bs_wait:
					if (uart_brdy)
						bstate <= bs_next;
				bs_next: begin
					bstate <= bs_idle;
				end
			endcase
		end
	end
		

	assign myreq = Breq_i && (addr_i == ba);
	assign uart_addr = addr_i[31:2];
	assign data_o=(bstate==bs_wait || bstate==bs_next)?uart_dout:32'hZZZZZZZZ;
	assign reqp_o=(myreq || bstate==bs_wait)?uart_reqp:1'bz;
	assign Brdy_o=(myreq || bstate==bs_wait)?uart_brdy:1'bz;
	
	uart_mp uart_dev
	 (	.clk(uartclk_i),
		.vamp_clk(clk_i),
		.reset(reset_i),
		.MDat_in(data_i),
		.MAddr(uart_addr),
      .req(Breq_i),
      .wr(WR_i),
      .MDat_out(uart_dout),
      .reqp(uart_reqp),
      .BRdy(uart_brdy),
		.TxD(TX),
      .RxD(RX),
		.dev_id(dev_id)
	 );



endmodule
