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

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbuexec.v] - Rev 38

Go to most recent revision | Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
// Filename:	wbuexec.v
//
// Project:	XuLA2 board
//
// Purpose:	This is the part of the USB-JTAG to wishbone conversion that
//		actually conducts a wishbone transaction.  Transactions are
//	requested via codewords that come in, and the results recorded on
//	codewords that are sent out.  Compression and/or decompression, coding
//	etc. all take place external to this routine.
//
//
// 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
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module	wbuexec(i_clk, i_rst, i_stb, i_codword, o_busy,
		o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
			i_wb_ack, i_wb_stall, i_wb_err, i_wb_data,
		o_stb, o_codword);
	input			i_clk, i_rst;
	// The command inputs
	input			i_stb;
	input		[35:0]	i_codword;
	output	reg	o_busy;
	// Wishbone outputs
	output	reg		o_wb_cyc, o_wb_stb, o_wb_we;
	output	reg	[31:0]	o_wb_addr, o_wb_data;
	// Wishbone inputs
	input			i_wb_ack, i_wb_stall, i_wb_err;
	input		[31:0]	i_wb_data;
	// And our codeword outputs
	output	reg		o_stb;
	output	reg	[35:0]	o_codword;
 
 
	wire	w_accept, w_eow, w_newwr, w_new_err;
	// wire	w_newad, w_newrd;
	assign	w_accept = (i_stb)&&(~o_busy);
	// assign	w_newad  = (w_accept)&&(i_codword[35:34] == 2'b00);
	assign	w_newwr  = (w_accept)&&(i_codword[35:34] == 2'b01);
	assign	w_eow    = (w_accept)&&(i_codword[35:30] == 6'h2e);
	// assign	w_newrd  = (w_accept)&&(i_codword[35:34] == 2'b11);
	wire	[31:0]	w_cod_data;
	assign	w_cod_data={ i_codword[32:31], i_codword[29:0] }; 
	assign	w_new_err = ((w_accept)
				&&((i_codword[35:33] != 3'h3)||(~o_wb_we))
				&&(i_codword[35:30] != 6'h2e));
 
	reg	[9:0]	r_acks_needed, r_len;
 
	reg	r_inc, r_wb_err, r_new_addr, r_eow;
	initial r_wb_err = 1'b0;
	initial	r_new_addr = 1'b1;
	always @(posedge i_clk)
		if (i_rst)
		begin
			o_stb <= 1'b1;
			o_codword <= { 6'h3, 30'h000 };
			r_wb_err <= 1'b0;
			o_wb_cyc <= 1'b0;
		end else if (o_wb_cyc) // In the middle of a bus transaction
		begin
			o_stb <= 1'b0;
 
			// Deal with bus errors
			if (r_wb_err)
			begin
				if (w_eow)
					o_wb_cyc <= 1'b0;
				o_wb_stb <= 1'b0;
			end else if ((i_wb_err)||(w_new_err))
			begin
				o_wb_cyc <= (~o_busy);
				o_wb_stb <= 1'b0;
				r_wb_err <= 1'b1;
				//
				o_stb <= 1'b1;
				o_codword <= { 6'h5, 30'h0000 };
				//
			end else if ((o_wb_stb)&&(~i_wb_stall))
			// Deal with the strobe line
			begin // Strobe was accepted, busy should be '1' here
				if (r_len != 0) // read
					r_len <= r_len - 10'h01;
				else
					o_wb_stb <= 1'b0;
 
				if (o_wb_we)
				begin // Acknowledge a write
					o_stb <= 1'b1;
					o_codword <= { 6'h2, 30'h0000 };
				end
 
				if (r_inc)
					o_wb_addr <= o_wb_addr + 32'h001;
			end else if (w_newwr) begin
				r_inc <= i_codword[30];
				o_wb_data <= w_cod_data;
				o_wb_stb <= 1'b1;
			/*
			end else if (w_newrd)
			begin // This seems good, but it would stall the bus
				// BUS ERROR!
				o_wb_cyc <= 1'b0;
				o_stb <= 1'b1;
				o_codword <= { 4'h5, 32'h0000 };
			*/
			end
 
			if (w_eow)
				r_eow <= 1'b1;
 
			if ((r_wb_err)||(i_wb_err)||(w_new_err))
				// On an error, flush any inputs ...
				o_busy <= 1'b0;
			else if ((w_eow)||(w_newwr)||(r_eow))
				// On a new command, we're busy again
				o_busy <= 1'b1;
			else if((o_wb_we)&&(o_wb_stb)&&(~i_wb_stall)&&(r_len==0))
				// Once our command completes, if it was a write
				// command, then 
				o_busy <= 1'b0;
			else if ((o_wb_we)&&(~o_wb_stb))
				o_busy <= 1'b0;
 
			//
			// Now let's process the acknowledgements
			//
			if ((r_wb_err)||(i_wb_err))
			begin
				// Acks are irrelevant here
			end else if (r_acks_needed != 10'h00)
			begin
				if ((i_wb_ack)&&(~o_wb_we))
				begin // Return a read result
				o_stb <= 1'b1;
				o_codword <= { 3'h7, i_wb_data[31:30], r_inc,
					i_wb_data[29:0] };
				end
 
				if ((i_wb_ack)&&(~w_newwr))
					r_acks_needed <= r_acks_needed - 10'h001;
				else if ((~i_wb_ack)&&(w_newwr))
					r_acks_needed <= r_acks_needed + 10'h001;
			end else if (r_acks_needed == 10'h0)
			begin
				if ((~o_wb_we)||(r_eow)||(w_eow)) // End our bus cycle
					o_wb_cyc <= 1'b0;
				else if (w_newwr)
				begin
					r_acks_needed <= r_acks_needed + 10'h001;
					o_wb_data <= w_cod_data;
				end
			end
		//
		//
		//
		//
		//
		end else if (i_stb)
		//
		//
		//
		//
		//
		begin
			// Default is not to send any codewords
			o_stb    <= 1'b0;
			// Increment addresses?
			r_inc <= i_codword[30];
			// Will this be a write?
			o_wb_we <= (~i_codword[35]);
			// Do we need to broadcast a new address?
			// r_new_addr <= 1'b0;
			// Errors are all clear by now
			r_wb_err <= 1'b0;
			// Need to be not-busy when o_wb_cyc is low
			o_busy   <= 1'b0;
			// 
			r_eow <= 1'b0;
			if (i_codword[35:32] == 4'h0)
			begin // Set a new address
				r_new_addr <= 1'b1;
				o_wb_addr <= i_codword[31:0];
			end else if (i_codword[35:33] == 3'b001)
			begin // Set a new relative address
				o_wb_addr <= o_wb_addr
					+ { i_codword[32:31], i_codword[29:0] };
				r_new_addr <= 1'b1;
			end else if (i_codword[35:34] == 2'b11)
			begin // Start a vector read
				// Address is already set ...
				// This also depends upon the decoder working
				r_len <= i_codword[9:0] - 10'h01;
				o_wb_cyc <= 1'b1;
				o_wb_stb <= 1'b1;
				r_acks_needed <= i_codword[9:0];
				o_busy   <= 1'b1;
 
				if (r_new_addr)
				begin
					o_stb <= 1'b1;
					o_codword <= { 4'h2, o_wb_addr };
					r_new_addr <= 1'b0;
				end
			end else if (~i_codword[35])
			begin // Start a write transaction, address is alrdy set
				o_wb_cyc <= 1'b1;
				o_wb_stb <= 1'b1;
				o_wb_data <= w_cod_data; 
				o_busy   <= 1'b1;
				r_len <= 10'h00;
				r_new_addr <= 1'b1;
				r_acks_needed <= 10'h01;
			end
		end else begin
			r_wb_err <= 1'b0;
			o_busy   <= 1'b0;
			o_stb    <= 1'b0;
		end
 
endmodule
 

Go to most recent revision | 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.