`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:13:53 06/19/2006 
// Design Name: 
// Module Name:    bootrom 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
// 
//////////////////////////////////////////////////////////////////////////////////
module bootrom(clk_i, reset_i, data_o, addr_i, Breq_i, Brdy_o, reqp_o);
    input clk_i;
    input reset_i;
    output [31:0] data_o;
    input [31:0] addr_i;
    input Breq_i;
    output Brdy_o;
	 output reqp_o;

	reg [31:0] bootrom [0:31]; // The array needs this order for readmemh!
	reg [1:0] bstate;
	reg [31:0] val;
	wire myreq;
	
	
		// FSM states
	parameter bs_idle = 3'd0;
	parameter bs_wait = 3'd1;
	parameter bs_ack	= 3'd2;
	parameter bs_next = 3'd3;
	
	assign myreq=Breq_i && (addr_i[31:5] == 27'h0);
	assign data_o=bstate!=bs_idle?val:32'hZ;
	assign reqp_o=(myreq || bstate==bs_wait)?1:bstate==bs_ack?0:1'bz;
	assign Brdy_o=(myreq || bstate==bs_wait)?0:bstate==bs_ack?1:1'bz;
	
	

	initial 	 $readmemh("boot.mem", bootrom);
	

	always @(posedge clk_i or posedge reset_i) begin
		if (reset_i)
			bstate<=bs_idle;
		else
			case (bstate)
				bs_idle:
					if (myreq)
						bstate <= bs_wait;
				bs_wait: begin
					val <= bootrom[(addr_i[4:0])];
					bstate <= bs_ack;
				end
				bs_ack:
					bstate <= bs_next;
				bs_next:
					bstate <= bs_idle;
			endcase
	end

endmodule
