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

Subversion Repositories ata

[/] [ata/] [trunk/] [rtl/] [verilog/] [ocidec-2/] [atahost_wb_slave.v] - Rev 33

Compare with Previous | Blame | View Log

/////////////////////////////////////////////////////////////////////
////                                                             ////
////  OCIDEC-1 ATA/ATAPI-5 Controller                            ////
////  Wishbone Slave interface (common for all OCIDEC cores)     ////
////                                                             ////
////  Author: Richard Herveille                                  ////
////          richard@asics.ws                                   ////
////          www.asics.ws                                       ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2001, 2002 Richard Herveille                  ////
////                          richard@asics.ws                   ////
////                                                             ////
//// This source file may be used and distributed without        ////
//// restriction provided that this copyright statement is not   ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
////                                                             ////
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
 
//
//  CVS Log
//
//  $Id: atahost_wb_slave.v,v 1.1 2002-02-18 14:26:46 rherveille Exp $
//
//  $Date: 2002-02-18 14:26:46 $
//  $Revision: 1.1 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               $Log: not supported by cvs2svn $
//
 
`include "timescale.v"
 
module atahost_wb_slave (
		clk_i, arst_i, rst_i, cyc_i, stb_i, ack_o, rty_o, err_o, adr_i,	dat_i, dat_o, sel_i, we_i, inta_o,
		PIOsel, PIOtip, PIOack, PIOq, PIOpp_full, irq,
		DMAsel, DMAtip, DMAack, DMARxEmpty, DMATxFull, DMA_dmarq, DMAq,
		IDEctrl_rst, IDEctrl_IDEen, IDEctrl_FATR1, IDEctrl_FATR0, IDEctrl_ppen,
		DMActrl_DMAen, DMActrl_dir, DMActrl_BeLeC0, DMActrl_BeLeC1,
		PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc, PIO_cmdport_IORDYen,
		PIO_dport0_T1, PIO_dport0_T2, PIO_dport0_T4, PIO_dport0_Teoc, PIO_dport0_IORDYen,
		PIO_dport1_T1, PIO_dport1_T2, PIO_dport1_T4, PIO_dport1_Teoc, PIO_dport1_IORDYen,
		DMA_dev0_Tm, DMA_dev0_Td, DMA_dev0_Teoc, DMA_dev1_Tm, DMA_dev1_Td, DMA_dev1_Teoc
	);
 
	//
	// Parameters
	//
	parameter DeviceId   = 4'h0;
	parameter RevisionNo = 4'h0;
 
	// PIO mode 0 settings (@100MHz clock)
	parameter PIO_mode0_T1   =  6;                // 70ns
	parameter PIO_mode0_T2   = 28;                // 290ns
	parameter PIO_mode0_T4   =  2;                // 30ns
	parameter PIO_mode0_Teoc = 23;                // 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
 
	// Multiword DMA mode 0 settings (@100MHz clock)
	parameter DMA_mode0_Tm   =  6;                // 50ns
	parameter DMA_mode0_Td   = 21;                // 215ns
	parameter DMA_mode0_Teoc = 21;                // 215ns ==> T0 - Td - Tm = 480 - 50 - 215 = 215
 
	//
	// inputs & outputs
	//
 
	// WISHBONE SYSCON signals
	input clk_i;                                // master clock in
	input arst_i;                               // asynchronous active low reset
	input rst_i;                                // synchronous active high reset
 
	// WISHBONE SLAVE signals
	input       cyc_i;                          // valid bus cycle input
	input       stb_i;                          // strobe/core select input
	output      ack_o;                          // strobe acknowledge output
	output      rty_o;                          // retry output
	output      err_o;                          // error output
	input [6:2] adr_i;                          // A6 = '1' ATA devices selected
	                                            //          A5 = '1' CS1- asserted, '0' CS0- asserted
	                                            //          A4..A2 ATA address lines
	                                            // A6 = '0' ATA controller selected
	input  [31:0] dat_i;                        // Databus in
	output [31:0] dat_o;                        // Databus out
	input  [ 3:0] sel_i;                        // Byte select signals
	input         we_i;                         // Write enable input
	output        inta_o;                       // interrupt request signal IDE0
 
	// PIO control input
	output        PIOsel;
	input         PIOtip;                       // PIO transfer in progress
	input         PIOack;                       // PIO acknowledge signal
	input  [15:0] PIOq;                         // PIO data input
	input         PIOpp_full;                   // PIO write-ping-pong buffers full
	input         irq;                          // interrupt signal input
 
	// DMA control inputs
	output       DMAsel;
	input        DMAtip;                        // DMA transfer in progress
	input        DMAack;                        // DMA transfer acknowledge
	input        DMARxEmpty;                    // DMA receive buffer empty
	input        DMATxFull;                     // DMA transmit buffer full
	input        DMA_dmarq;                     // wishbone DMA request
	input [31:0] DMAq;
 
	// outputs
	// control register outputs
	output IDEctrl_rst;
	output IDEctrl_IDEen;
	output IDEctrl_FATR1;
	output IDEctrl_FATR0;
	output IDEctrl_ppen;
	output DMActrl_DMAen;
	output DMActrl_dir;
	output DMActrl_BeLeC0;
	output DMActrl_BeLeC1;
 
	// CMD port timing registers
	output [7:0] PIO_cmdport_T1,
	             PIO_cmdport_T2,
	             PIO_cmdport_T4,
	             PIO_cmdport_Teoc;
	output       PIO_cmdport_IORDYen;
 
	reg [7:0] PIO_cmdport_T1,
	          PIO_cmdport_T2,
	          PIO_cmdport_T4,
	          PIO_cmdport_Teoc;
 
	// data-port0 timing registers
	output [7:0] PIO_dport0_T1,
	             PIO_dport0_T2,
	             PIO_dport0_T4,
	             PIO_dport0_Teoc;
	output       PIO_dport0_IORDYen;
 
	reg [7:0] PIO_dport0_T1,
	          PIO_dport0_T2,
	          PIO_dport0_T4,
	          PIO_dport0_Teoc;
 
	// data-port1 timing registers
	output [7:0] PIO_dport1_T1,
	             PIO_dport1_T2,
	             PIO_dport1_T4,
	             PIO_dport1_Teoc;
	output       PIO_dport1_IORDYen;
 
	reg [7:0] PIO_dport1_T1,
	          PIO_dport1_T2,
	          PIO_dport1_T4,
	          PIO_dport1_Teoc;
 
	// DMA device0 timing registers
	output [7:0] DMA_dev0_Tm,
	             DMA_dev0_Td,
	             DMA_dev0_Teoc;
 
	reg [7:0] DMA_dev0_Tm,
	          DMA_dev0_Td,
	          DMA_dev0_Teoc;
 
	// DMA device1 timing registers
	output [7:0] DMA_dev1_Tm,
	             DMA_dev1_Td,
	             DMA_dev1_Teoc;
 
	reg [7:0] DMA_dev1_Tm,
	          DMA_dev1_Td,
	          DMA_dev1_Teoc;
 
 
	//
	// constants
	//
 
	// addresses
	`define ATA_DEV_ADR adr_i[6]
	`define ATA_ADR     adr_i[5:2]
 
	`define ATA_CTRL_REG 4'b0000
	`define ATA_STAT_REG 4'b0001
	`define ATA_PIO_CMD  4'b0010
	`define ATA_PIO_DP0  4'b0011
	`define ATA_PIO_DP1  4'b0100
	`define ATA_DMA_DEV0 4'b0101
	`define ATA_DMA_DEV1 4'b0110
	// reserved //
	`define ATA_DMA_PORT 4'b1111
 
 
	//
	// signals
	//
 
	// registers
	reg  [31:0] CtrlReg; // control register
	wire [31:0] StatReg; // status register
 
	// store ping-pong-full signal
	reg store_pp_full;
 
 
	//
	// generate bus cycle / address decoder
	//
	wire w_acc  = &sel_i[1:0];                        // word access
	wire dw_acc = &sel_i;                             // double word access
 
	// bus error
	wire berr = `ATA_DEV_ADR ? !w_acc : !dw_acc;
 
	// PIO accesses at least 16bit wide, no PIO access during DMAtip or pingpong-full
	wire PIOsel = cyc_i & stb_i & `ATA_DEV_ADR & w_acc & !(DMAtip | store_pp_full);
 
	// CON accesses only 32bit wide
	wire CONsel = cyc_i & stb_i & !(`ATA_DEV_ADR) & dw_acc;
	wire DMAsel = CONsel & (`ATA_ADR == `ATA_DMA_PORT);
 
	// bus retry (OCIDEC-3 and above)
	// store PIOpp_full, we don't want a PPfull based retry initiated by the current bus-cycle
	always@(posedge clk_i)
		if (!PIOsel)
			store_pp_full <= #1 PIOpp_full;
 
	wire brty = (`ATA_DEV_ADR & w_acc) & (DMAtip | store_pp_full);
 
	//
	// generate registers
	//
 
	// generate register select signals
	wire sel_ctrl        = CONsel & we_i & (`ATA_ADR == `ATA_CTRL_REG);
	wire sel_stat        = CONsel & we_i & (`ATA_ADR == `ATA_STAT_REG);
	wire sel_PIO_cmdport = CONsel & we_i & (`ATA_ADR == `ATA_PIO_CMD);
	wire sel_PIO_dport0  = CONsel & we_i & (`ATA_ADR == `ATA_PIO_DP0);
	wire sel_PIO_dport1  = CONsel & we_i & (`ATA_ADR == `ATA_PIO_DP1);
	wire sel_DMA_dev0    = CONsel & we_i & (`ATA_ADR == `ATA_DMA_DEV0);
	wire sel_DMA_dev1    = CONsel & we_i & (`ATA_ADR == `ATA_DMA_DEV1);
	// reserved 0x1c-0x38
	// reserved 0x3c : DMA-port
 
 
	// generate control register
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				CtrlReg[31:1] <= #1 0;
				CtrlReg[0]    <= #1 1'b1; // set reset bit (ATA-RESETn line)
			end
		else if (rst_i)
			begin
				CtrlReg[31:1] <= #1 0;
				CtrlReg[0]    <= #1 1'b1; // set reset bit (ATA-RESETn line)
			end
		else if (sel_ctrl)
			CtrlReg <= #1 dat_i;
 
	// assign bits
	assign DMActrl_DMAen        = CtrlReg[15];
	assign DMActrl_dir          = CtrlReg[13];
	assign DMActrl_BeLeC1       = CtrlReg[9];
	assign DMActrl_BeLeC0       = CtrlReg[8];
	assign IDEctrl_IDEen        = CtrlReg[7];
	assign IDEctrl_FATR1        = CtrlReg[6];
	assign IDEctrl_FATR0        = CtrlReg[5];
	assign IDEctrl_ppen         = CtrlReg[4];
	assign PIO_dport1_IORDYen   = CtrlReg[3];
	assign PIO_dport0_IORDYen   = CtrlReg[2];
	assign PIO_cmdport_IORDYen  = CtrlReg[1];
	assign IDEctrl_rst          = CtrlReg[0];
 
 
	// generate status register clearable bits
	reg dirq, int;
 
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				int  <= #1 1'b0;
				dirq <= #1 1'b0;
			end
		else if (rst_i)
			begin
				int  <= #1 1'b0;
				dirq <= #1 1'b0;
			end
		else
			begin
				int  <= #1 (int | (irq & !dirq)) & !(sel_stat & !dat_i[0]);
				dirq <= #1 irq;
			end
 
	// assign status bits
	assign StatReg[31:28] = DeviceId;   // set Device ID
	assign StatReg[27:24] = RevisionNo; // set revision number
	assign StatReg[23:16] = 0;          // reserved
	assign StatReg[15]    = DMAtip;
	assign StatReg[14:11] = 0;
	assign StatReg[10]    = DMARxEmpty;
	assign StatReg[9]     = DMATxFull;
	assign StatReg[8]     = DMA_dmarq;
	assign StatReg[7]     = PIOtip;
	assign StatReg[6]     = PIOpp_full;
	assign StatReg[5:1]   = 0;          // reserved
	assign StatReg[0]     = int;
 
 
	// generate PIO compatible / command-port timing register
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				PIO_cmdport_T1   <= #1 PIO_mode0_T1;
				PIO_cmdport_T2   <= #1 PIO_mode0_T2;
				PIO_cmdport_T4   <= #1 PIO_mode0_T4;
				PIO_cmdport_Teoc <= #1 PIO_mode0_Teoc;
			end
		else if (rst_i)
			begin
				PIO_cmdport_T1   <= #1 PIO_mode0_T1;
				PIO_cmdport_T2   <= #1 PIO_mode0_T2;
				PIO_cmdport_T4   <= #1 PIO_mode0_T4;
				PIO_cmdport_Teoc <= #1 PIO_mode0_Teoc;
			end
		else if(sel_PIO_cmdport)
			begin
				PIO_cmdport_T1   <= #1 dat_i[ 7: 0];
				PIO_cmdport_T2   <= #1 dat_i[15: 8];
				PIO_cmdport_T4   <= #1 dat_i[23:16];
				PIO_cmdport_Teoc <= #1 dat_i[31:24];
			end
 
	// generate PIO device0 timing register
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				PIO_dport0_T1   <= #1 PIO_mode0_T1;
				PIO_dport0_T2   <= #1 PIO_mode0_T2;
				PIO_dport0_T4   <= #1 PIO_mode0_T4;
				PIO_dport0_Teoc <= #1 PIO_mode0_Teoc;
			end
		else if (rst_i)
			begin
				PIO_dport0_T1   <= #1 PIO_mode0_T1;
				PIO_dport0_T2   <= #1 PIO_mode0_T2;
				PIO_dport0_T4   <= #1 PIO_mode0_T4;
				PIO_dport0_Teoc <= #1 PIO_mode0_Teoc;
			end
		else if(sel_PIO_dport0)
			begin
				PIO_dport0_T1   <= #1 dat_i[ 7: 0];
				PIO_dport0_T2   <= #1 dat_i[15: 8];
				PIO_dport0_T4   <= #1 dat_i[23:16];
				PIO_dport0_Teoc <= #1 dat_i[31:24];
			end
 
	// generate PIO device1 timing register
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				PIO_dport1_T1   <= #1 PIO_mode0_T1;
				PIO_dport1_T2   <= #1 PIO_mode0_T2;
				PIO_dport1_T4   <= #1 PIO_mode0_T4;
				PIO_dport1_Teoc <= #1 PIO_mode0_Teoc;
			end
		else if (rst_i)
			begin
				PIO_dport1_T1   <= #1 PIO_mode0_T1;
				PIO_dport1_T2   <= #1 PIO_mode0_T2;
				PIO_dport1_T4   <= #1 PIO_mode0_T4;
				PIO_dport1_Teoc <= #1 PIO_mode0_Teoc;
			end
		else if(sel_PIO_dport1)
			begin
				PIO_dport1_T1   <= #1 dat_i[ 7: 0];
				PIO_dport1_T2   <= #1 dat_i[15: 8];
				PIO_dport1_T4   <= #1 dat_i[23:16];
				PIO_dport1_Teoc <= #1 dat_i[31:24];
			end
 
	// generate DMA device0 timing register
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				DMA_dev0_Tm   <= #1 DMA_mode0_Tm;
				DMA_dev0_Td   <= #1 DMA_mode0_Td;
				DMA_dev0_Teoc <= #1 DMA_mode0_Teoc;
			end
		else if (rst_i)
			begin
				DMA_dev0_Tm   <= #1 DMA_mode0_Tm;
				DMA_dev0_Td   <= #1 DMA_mode0_Td;
				DMA_dev0_Teoc <= #1 DMA_mode0_Teoc;
			end
		else if(sel_DMA_dev0)
			begin
				DMA_dev0_Tm   <= #1 dat_i[ 7: 0];
				DMA_dev0_Td   <= #1 dat_i[15: 8];
				DMA_dev0_Teoc <= #1 dat_i[31:24];
			end
 
	// generate DMA device1 timing register
	always@(posedge clk_i or negedge arst_i)
		if (~arst_i)
			begin
				DMA_dev1_Tm   <= #1 DMA_mode0_Tm;
				DMA_dev1_Td   <= #1 DMA_mode0_Td;
				DMA_dev1_Teoc <= #1 DMA_mode0_Teoc;
			end
		else if (rst_i)
			begin
				DMA_dev1_Tm   <= #1 DMA_mode0_Tm;
				DMA_dev1_Td   <= #1 DMA_mode0_Td;
				DMA_dev1_Teoc <= #1 DMA_mode0_Teoc;
			end
		else if(sel_DMA_dev1)
			begin
				DMA_dev1_Tm   <= #1 dat_i[ 7: 0];
				DMA_dev1_Td   <= #1 dat_i[15: 8];
				DMA_dev1_Teoc <= #1 dat_i[31:24];
			end
 
	//
	// generate WISHBONE interconnect signals
	//
	reg [31:0] Q;
 
	// generate acknowledge signal
	assign ack_o = PIOack | CONsel; // | DMAack; // since DMAack is derived from CONsel this is OK
 
	// generate error signal
	assign err_o = cyc_i & stb_i & berr;
 
	// generate retry signal (for OCIDEC-3 and above only)
	assign rty_o = cyc_i & stb_i & brty;
 
	// generate interrupt signal
	assign inta_o = StatReg[0];
 
	// generate output multiplexor
	always@(`ATA_ADR or CtrlReg or StatReg or 
			PIO_cmdport_T1 or PIO_cmdport_T2 or PIO_cmdport_T4 or PIO_cmdport_Teoc or
			PIO_dport0_T1 or PIO_dport0_T2 or PIO_dport0_T4 or PIO_dport0_Teoc or
			PIO_dport1_T1 or PIO_dport1_T2 or PIO_dport1_T4 or PIO_dport1_Teoc or
			DMA_dev0_Tm or DMA_dev0_Td or DMA_dev0_Teoc or
			DMA_dev1_Tm or DMA_dev1_Td or DMA_dev1_Teoc or
			DMAq
		)
		case (`ATA_ADR) // synopsis full_case parallel_case
			`ATA_CTRL_REG: Q = CtrlReg;
			`ATA_STAT_REG: Q = StatReg;
			`ATA_PIO_CMD : Q = {PIO_cmdport_Teoc, PIO_cmdport_T4, PIO_cmdport_T2, PIO_cmdport_T1};
			`ATA_PIO_DP0 : Q = {PIO_dport0_Teoc, PIO_dport0_T4, PIO_dport0_T2, PIO_dport0_T1};
			`ATA_PIO_DP1 : Q = {PIO_dport1_Teoc, PIO_dport1_T4, PIO_dport1_T2, PIO_dport1_T1};
			`ATA_DMA_DEV0: Q = {DMA_dev0_Teoc, 8'h0, DMA_dev0_Td, DMA_dev0_Tm};
			`ATA_DMA_DEV1: Q = {DMA_dev1_Teoc, 8'h0, DMA_dev1_Td, DMA_dev1_Tm};
			`ATA_DMA_PORT: Q = DMAq;
			default: Q = 0;
		endcase
 
	// assign DAT_O output
	assign dat_o = `ATA_DEV_ADR ? {16'h0, PIOq} : Q;
 
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.