OpenCores
URL https://opencores.org/ocsvn/wbicapetwo/wbicapetwo/trunk

Subversion Repositories wbicapetwo

[/] [wbicapetwo/] [trunk/] [rtl/] [wbicapetwo.v] - Rev 4

Compare with Previous | Blame | View Log

///////////////////////////////////////////////////////////////////////////
//
// Filename:	wbicapetwo.v
//
// Project:	Wishbone to ICAPE2 interface conversion
//
// Purpose:	This routine maps the configuration registers of a 7-series
//		Xilinx part onto register addresses on a wishbone bus interface
//		via the ICAPE2 access port to those parts.  The big thing this
//		captures is the timing and handshaking required to read and
//		write registers from the configuration interface.
//
//		As an example of what can be done, writing a 32'h00f to
//		local address 5'h4 sends the IPROG command to the FPGA, causing
//		it to immediately reconfigure itself.
//
//		As another example, the warm boot start address is located
//		in register 5'h10.  Writing to this address, followed by
//		issuing the IPROG command just mentioned will cause the
//		FPGA to configure from that warm boot start address.
// 
//		For more details on the configuration interface, the registers
//		in question, their meanings and what they do, please see
//		User's Guide 470, the "7 Series FPGAs Configuration" User
//		Guide.
//
// Notes:	This module supports both reads and writes from the ICAPE2
//		interface.  These follow the following pattern.
//
//	For writes:
//		(Idle)	0xffffffff	(Dummy)
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0xaa995566	SYNC WORD
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	...		Write command
//		(CS/W)	...		Write value, from Wishbone bus
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x30008001	Write to CMD register (address 4)
//		(CS/W)	0x0000000d	DESYNC command
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(Idle)
//
//	and for reads:
//		(Idle)	0xffffffff	(Dummy)
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0xaa995566	SYNC WORD
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	...		Read command
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(Idle)	0x20000000	(Idle the interface again, so we can rd)
//		(CS/R)	0x20000000	(Wait)
//		(CS/R)	0x20000000	(Wait)
//		(CS/R)	0x20000000	(Wait)
//		(CS/R)	0x20000000	(Wait)
//		(Idle)	0x20000000	(Idle the interface before writing)
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x30008001	Write to CMD register (address 4)
//		(CS/W)	0x0000000d	DESYNC command
//		(CS/W)	0x20000000	NOOP
//		(CS/W)	0x20000000	NOOP
//		(Idle)
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// License:	GPL, v3, as defined and found on www.gnu.org,
//		http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
//
`define	MBOOT_IDLE	5'h00
`define	MBOOT_START	5'h01
`define	MBOOT_READ	5'h06
`define	MBOOT_WRITE	5'h0f
`define	MBOOT_DESYNC	5'h11
module	wbicapetwo(i_clk,
		i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
			o_wb_ack, o_wb_stall, o_wb_data);
	input			i_clk;
	// Wishbone inputs
	input			i_wb_cyc, i_wb_stb, i_wb_we;
	input		[4:0]	i_wb_addr;
	input		[31:0]	i_wb_data;
	// Wishbone outputs
	output	reg		o_wb_ack, o_wb_stall;
	output	reg	[31:0]	o_wb_data;
	// ICAPE2 interface signals
	//	These are kept internal to this block ...
 
	reg		wb_req, r_we;
	reg	[31:0]	r_data;
	reg	[4:0]	r_addr;
 
	reg	[31:0]	cfg_in;
	reg		cfg_cs_n, cfg_rdwrn;
	wire	[31:0]	cfg_out;
	reg	[4:0]	state;
	initial	state = `MBOOT_IDLE;
	initial	cfg_cs_n = 1'b1;
	always @(posedge i_clk)
	begin
		o_wb_ack <= 1'b0;
		o_wb_stall <= 1'b1;
		state <= state + 5'h01;
		wb_req <= wb_req & i_wb_cyc;
		case(state)
		`MBOOT_IDLE: begin
			cfg_cs_n <= 1'b1;
			cfg_rdwrn <= 1'b1;
			cfg_in <= 32'hffffffff;	// Dummy word
 
			state <= `MBOOT_IDLE;
 
			o_wb_ack <= 1'b0;
			o_wb_stall <= 1'b0;
 
			r_addr <= i_wb_addr;
			r_data <= i_wb_data;
			r_we   <= i_wb_we;
			if((i_wb_cyc)&&(i_wb_stb))
			begin
				state <= `MBOOT_START;
				wb_req <= 1'b1;
				//
				o_wb_ack <= 1'b0;
				o_wb_stall <= 1'b1;
			end end
		`MBOOT_START: cfg_in <= 32'hffffffff; // NOOP
		5'h02: begin
			cfg_cs_n <= 1'b0; // Activate interface
			cfg_rdwrn <= 1'b0;
			cfg_in <= 32'h20000000;	// NOOP
			end
		5'h03: cfg_in <= 32'haa995566;	// Sync word
		5'h04: cfg_in <= 32'h20000000; // NOOP
		5'h05: begin
			cfg_in <= 32'h20000000;	// NOOP
			state <= (r_we) ? `MBOOT_WRITE : `MBOOT_READ;
			end
		`MBOOT_READ: cfg_in <= { 8'h28, 6'h0, r_addr, 13'h001 };
		5'h07: cfg_in <= 32'h20000000; // NOOP
		5'h08: cfg_in <= 32'h20000000; // NOOP
		5'h09: begin // Idle the interface before the read cycle
			cfg_cs_n <= 1'b1;
			cfg_rdwrn <= 1'b1;
			cfg_in <= 32'h20000000; // NOOP
			end
		5'h0a: begin // Re-activate the interface and wait 3 cycles
			cfg_cs_n <= 1'b0;
			cfg_rdwrn <= 1'b1;
			cfg_in <= 32'h20000000; // NOOP
			end
		5'h0b: // ... still waiting, cycle two
			cfg_in <= 32'h20000000; // NOOP
		5'h0c: // ... still waiting, cycle three
			cfg_in <= 32'h20000000; // NOOP
		5'h0d: // ... still waiting, cycle four
			cfg_in <= 32'h20000000; // NOOP
		5'h0e: begin // and now our answer is there
			cfg_cs_n <= 1'b1;
			cfg_rdwrn <= 1'b1;
			cfg_in <= 32'h20000000; // NOOP
			//
			// Wishbone return
			o_wb_ack <= wb_req;
			o_wb_data <= cfg_out;
			wb_req <= 1'b0;
			//
			state <= `MBOOT_DESYNC;
			end
		`MBOOT_WRITE:	// Issue a write command to the given address
			cfg_in <= { 8'h30, 6'h0, r_addr, 13'h001 };
		5'h10: cfg_in <= r_data;	// Write the value
		`MBOOT_DESYNC: begin
			cfg_cs_n <= 1'b0;
			cfg_rdwrn <= 1'b0;
			cfg_in <= 32'h20000000;	// 1st NOOP
			end
		5'h12: cfg_in <= 32'h20000000;	// 2nd NOOP
		5'h13: cfg_in <= 32'h30008001;	// Write to CMD register
		5'h14: cfg_in <= 32'h0000000d;	// DESYNC command
		5'h15: cfg_in <= 32'h20000000;	// NOOP
		5'h16: cfg_in <= 32'h20000000;	// NOOP
		5'h17: begin
			// Acknowledge the bus transaction, it is now complete
			o_wb_ack <= wb_req;
			o_wb_stall <= 1'b0;
			wb_req <= 1'b0;
			//
			cfg_cs_n <= 1'b1;
			cfg_rdwrn <= 1'b0;
			cfg_in <= 32'hffffffff;	// DUMMY
			//
			state <= `MBOOT_IDLE;
			end
		default: begin
			o_wb_ack <= 1'b0;
			o_wb_stall <= 1'b1;
			cfg_cs_n <= 1'b1;
			cfg_rdwrn <= 1'b0;
			state <= `MBOOT_IDLE;
			cfg_in <= 32'hffffffff;	// DUMMY WORD
			end
		endcase
	end
 
	genvar	k;
	//
	// The data registers to the ICAPE2 interface are bit swapped within
	// each byte.  Thus, in order to read from or write to the interface,
	// we need to bit swap the bits in each byte.  These next lines
	// accomplish that for both the input and output ports.
	//
	wire	[31:0]	bit_swapped_cfg_in;
	generate
	for(k=0; k<8; k=k+1)
	begin
		assign bit_swapped_cfg_in[   k] = cfg_in[   7-k];
		assign bit_swapped_cfg_in[ 8+k] = cfg_in[ 8+7-k];
		assign bit_swapped_cfg_in[16+k] = cfg_in[16+7-k];
		assign bit_swapped_cfg_in[24+k] = cfg_in[24+7-k];
	end endgenerate
 
	wire	[31:0]	bit_swapped_cfg_out;
	generate
	for(k=0; k<8; k=k+1)
	begin
		assign cfg_out[   k] = bit_swapped_cfg_out[   7-k];
		assign cfg_out[ 8+k] = bit_swapped_cfg_out[ 8+7-k];
		assign cfg_out[16+k] = bit_swapped_cfg_out[16+7-k];
		assign cfg_out[24+k] = bit_swapped_cfg_out[24+7-k];
	end endgenerate
 
	ICAPE2 #(.ICAP_WIDTH("X32")) reconfig(.CLK(i_clk),
			.CSIB(cfg_cs_n), .RDWRB(cfg_rdwrn),
			.I(bit_swapped_cfg_in), .O(bit_swapped_cfg_out));
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.