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

Subversion Repositories ata

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 8 to Rev 9
    Reverse comparison

Rev 8 → Rev 9

/trunk/verilog/ocidec-1/pio_tctrl.v
4,7 → 4,7
// author : Richard Herveille
// Rev. 1.0 June 27th, 2001. Initial Verilog release
// Rev. 1.1 July 2nd, 2001. Fixed incomplete port list and some Verilog related issues.
//
// Rev. 1.2 July 11th, 2001. Changed 'igo' & 'hold_go' generation.
 
//
///////////////////////////
119,10 → 119,10
else
begin
busy <= (igo | busy) & !Teoc_done;
hold_go <= go | (hold_go & busy);
hold_go <= (go | (hold_go & busy)) & !igo;
end
 
assign igo = hold_go & !busy;
assign igo = (go | hold_go) & !busy;
 
// 1) hookup T1 counter
ro_cnt #(TWIDTH) t1_cnt(.clk(clk), .nReset(nReset), .rst(rst), .cnt_en(1'b1), .go(igo), .d(T1), .id(T1_m0), .done(T1done), .q());
183,3 → 183,4
 
 
 
 
/trunk/verilog/ocidec-1/controller.v
4,8 → 4,8
// author : Richard Herveille
// rev.: 1.0 june 28th, 2001. Initial Verilog release
// rev.: 1.1 July 3rd, 2001. Rewrote "IORDY" and "INTRQ" capture section.
// rev.: 1.2 July 9th, 2001. Added "timescale". Undo "IORDY & INTRQ" rewrite.
//
// rev.: 1.2 July 9th, 2001. Added "timescale". Undid "IORDY & INTRQ" rewrite.
// rev.: 1.3 july 11th, 2001. Changed PIOreq & PIOack generation (made them synchronous).
 
// OCIDEC1 supports:
// -Common Compatible timing access to all connected devices
55,6 → 55,7
input PIOwe; // PIO direction bit. 1'b1==write, 1'b0==read
 
reg [15:0] PIOq;
reg PIOack;
 
// ATA signals
output RESETn;
83,7 → 84,7
//
 
reg dPIOreq;
wire PIOgo; // start PIO timing controller
reg PIOgo; // start PIO timing controller
wire PIOdone; // PIO timing controller done
 
// PIO signals
169,10 → 170,11
 
// generate PIOgo signal
always@(posedge clk)
begin
dPIOreq <= PIOreq & !PIOack;
PIOgo = (PIOreq & !dPIOreq) & IDEctrl_IDEen;
end
 
assign PIOgo = (PIOreq & !dPIOreq) & IDEctrl_IDEen;
 
// set Timing signals
assign T1 = PIO_cmdport_T1;
assign T2 = PIO_cmdport_T2;
185,8 → 187,10
PIO_timing_controller (.clk(clk), .nReset(nReset), .rst(rst), .IORDY_en(IORDYen), .T1(T1), .T2(T2), .T4(T4), .Teoc(Teoc),
.go(PIOgo), .we(PIOwe), .oe(PIOoe), .done(PIOdone), .dstrb(dstrb), .DIOR(PIOdior), .DIOW(PIOdiow), .IORDY(sIORDY) );
 
assign PIOack = PIOdone | (PIOreq & !IDEctrl_IDEen); // acknowledge when done or when IDE not enabled (discard request)
always@(posedge clk)
PIOack = PIOdone | (PIOreq & !IDEctrl_IDEen); // acknowledge when done or when IDE not enabled (discard request)
endmodule
 
 
 
 
/trunk/verilog/ocidec-1/atahost.v
0,0 → 1,231
//
// Project: AT Atachement interface
// ATA-3 rev7B compliant
// Author: Richard Herveille
// rev.: 1.0 June 29th, 2001. Initial Verilog release
// rev.: 1.1 July 3rd, 2001. Changed 'ADR_I[5:2]' into 'ADR_I' on output multiplexor sensitivity list.
// rev.: 1.2 July 9th, 2001. Fixed register control; registers latched data on all edge cycles instead when selected.
// rev.: 1.3 July 11th, 2001. Fixed case sensitivity error (nRESET instead of nReset) in "controller" module declaration.
 
// DeviceType: OCIDEC-1: OpenCores IDE Controller type1
// Features: PIO Compatible Timing
// DeviceID: 0x01
// RevNo : 0x00
 
//
// Host signals:
// Reset
// DIOR- read strobe. The falling edge enables data from device onto DD. The rising edge latches data at the host.
// DIOW- write strobe. The rising edge latches data from DD into the device.
// DA(2:0) 3bit binary coded adress
// CS0- select command block registers
// CS1- select control block registers
 
`timescale 1ns / 10ps
 
module atahost (CLK_I, nReset, RST_I, CYC_I, STB_I, ACK_O, ERR_O, ADR_I, DAT_I, DAT_O, SEL_I, WE_I, INTA_O,
RESETn, DDi, DDo, DDoe, DA, CS0n, CS1n, DIORn, DIOWn, IORDY, INTRQ);
//
// Parameter declarations
//
parameter TWIDTH = 8; // counter width
// 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
 
//
// inputs & outputs
//
 
// WISHBONE SYSCON signals
input CLK_I; // master clock in
input nReset; // = 1'b1; // asynchronous active low reset
input RST_I; // = 1'b0; // 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 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
 
// ATA signals
output RESETn;
input [15:0] DDi;
output [15:0] DDo;
output DDoe;
output [ 2:0] DA;
output CS0n;
output CS1n;
 
output DIORn;
output DIOWn;
input IORDY;
input INTRQ;
 
//
// constant declarations
//
parameter [3:0] DeviceId = 4'h1;
parameter [3:0] RevisionNo = 4'h0;
 
//
// Variable declarations
//
 
// registers
wire IDEctrl_IDEen, IDEctrl_rst;
reg [ 7:0] PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc;
wire PIO_cmdport_IORDYen;
reg [31:0] CtrlReg; // control register
 
wire PIOack;
wire [15:0] PIOq;
 
wire [31:0] stat;
 
wire irq; // ATA bus IRQ signal
 
/////////////////
// Module body //
/////////////////
 
// generate bus cycle / address decoder
wire w_acc = SEL_I[1] & SEL_I[0]; // word access
wire dw_acc = SEL_I[3] & SEL_I[2] & SEL_I[1] & SEL_I[0]; // double word access
 
// bus error
wire berr = ADR_I[6] ? !w_acc : !dw_acc;
 
// PIO accesses at least 16bit wide
wire PIOsel = CYC_I & STB_I & ADR_I[6] & w_acc;
 
// CON accesses only 32bit wide
wire CONsel = CYC_I & STB_I & !ADR_I[6] & dw_acc;
 
// generate registers
 
// generate register select signals
wire sel_ctrl = CONsel & WE_I & !ADR_I[5] & !ADR_I[4] & !ADR_I[3] & !ADR_I[2]; // 0x00
wire sel_stat = CONsel & WE_I & !ADR_I[5] & !ADR_I[4] & !ADR_I[3] & ADR_I[2]; // 0x01
wire sel_PIO_cmdport = CONsel & WE_I & !ADR_I[5] & !ADR_I[4] & ADR_I[3] & !ADR_I[2]; // 0x02
// reserved 0x03-0x0f --
 
// generate control register
always@(posedge CLK_I or negedge nReset)
if (~nReset)
begin
CtrlReg[31:1] <= 0;
CtrlReg[0] <= 1'b1; // set reset bit (ATA-RESETn line)
end
else if (RST_I)
begin
CtrlReg[31:1] <= 0;
CtrlReg[0] <= 1'b1; // set reset bit (ATA-RESETn line)
end
else if (sel_ctrl)
CtrlReg <= DAT_I;
 
// assign bits
assign IDEctrl_IDEen = CtrlReg[7];
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 nReset)
if (~nReset)
begin
int <= 1'b0;
dirq <= 1'b0;
end
else if (RST_I)
begin
int <= 1'b0;
dirq <= 1'b0;
end
else
begin
int <= (int | (irq & !dirq)) & !(sel_stat & !DAT_I[0]);
dirq <= irq;
end
 
// assign status bits
assign stat[31:28] = DeviceId; // set Device ID
assign stat[27:24] = RevisionNo; // set revision number
assign stat[23: 1] = 0; // --clear unused bits--
// Although stat[7]=PIOtip this bit is zero, because it is impossible
// to read the status register and access the PIO registers at the same time.
assign stat[0] = int;
 
 
// generate PIO compatible / command-port timing register
always@(posedge CLK_I or negedge nReset)
if (~nReset)
begin
PIO_cmdport_T1 = PIO_mode0_T1;
PIO_cmdport_T2 = PIO_mode0_T2;
PIO_cmdport_T4 = PIO_mode0_T4;
PIO_cmdport_Teoc = PIO_mode0_Teoc;
end
else if (RST_I)
begin
PIO_cmdport_T1 = PIO_mode0_T1;
PIO_cmdport_T2 = PIO_mode0_T2;
PIO_cmdport_T4 = PIO_mode0_T4;
PIO_cmdport_Teoc = PIO_mode0_Teoc;
end
else if(sel_PIO_cmdport)
begin
PIO_cmdport_T1 = DAT_I[ 7: 0];
PIO_cmdport_T2 = DAT_I[15: 8];
PIO_cmdport_T4 = DAT_I[23:16];
PIO_cmdport_Teoc = DAT_I[31:24];
end
 
 
//
// hookup controller section
//
controller #(TWIDTH, PIO_mode0_T1, PIO_mode0_T2, PIO_mode0_T4, PIO_mode0_Teoc)
u1 (CLK_I, nReset, RST_I, irq, IDEctrl_rst, IDEctrl_IDEen, PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc, PIO_cmdport_IORDYen,
PIOsel, PIOack, ADR_I[5:2], DAT_I[15:0], PIOq, WE_I, RESETn, DDi, DDo, DDoe, DA, CS0n, CS1n, DIORn, DIOWn, IORDY, INTRQ);
 
//
// generate WISHBONE interconnect signals
//
reg [31:0] Q;
 
// generate acknowledge signal
assign ACK_O = PIOack | CONsel;
 
// generate error signal
assign ERR_O = CYC_I & STB_I & berr;
 
// generate interrupt signal
assign INTA_O = stat[0];
// generate output multiplexor
always@(ADR_I or CtrlReg or stat or PIO_cmdport_T1 or PIO_cmdport_T2 or PIO_cmdport_T4 or PIO_cmdport_Teoc)
case (ADR_I[5:2])
4'b0000: Q = CtrlReg;
4'b0001: Q = stat;
4'b0010: Q = {PIO_cmdport_Teoc, PIO_cmdport_T4, PIO_cmdport_T2, PIO_cmdport_T1};
default: Q = 0;
endcase
 
// assign DAT_O output
assign DAT_O = ADR_I[6] ? {16'h0000, PIOq} : Q;
endmodule
/trunk/verilog/ocidec-1/revision_history.txt
34,4 → 34,7
Date: July 11th, 2001
Author: Richard Herveille
- Fixed case sensitivity error (nRESET instead of nReset) in "controller" module declaration.
- changed 'ata.v' into 'atahost.v'
- Changed PIOreq & PIOack generation (controller.vhd); made them synchronous
- Changed 'go' & 'igo' generation (pio_tctrl.vhdl).
-----------------------------
/trunk/vhdl/ocidec1/pio_tctrl.vhd
2,7 → 2,8
-- file: pio_tctrl.vhd
-- description: PIO mode timing controller for ATA controller
-- author : Richard Herveille
-- rev.: 1.0 march 7th, 2001
-- rev.: 1.0 march 7th, 2001. Initial release
-- rev.: 1.1 July 11th, 2001. Changed 'igo' & 'hold_go' signal generation.
--
 
--
126,11 → 127,11
hold_go <= '0';
else
busy <= (igo or busy) and not Teoc_done;
hold_go <= go or (hold_go and busy);
hold_go <= (go or (hold_go and busy)) and not igo;
end if;
end if;
end process;
igo <= hold_go and not busy;
igo <= (go or hold_go) and not busy;
 
-- 1) hookup T1 counter
t1_cnt : ro_cnt generic map (SIZE => TWIDTH)
205,3 → 206,9
 
 
 
 
 
 
 
 
 
/trunk/vhdl/ocidec1/controller.vhd
6,8 → 6,8
-- rev.: 1.0a april 12th, 2001. Removed references to records.vhd to make it compatible with freely available VHDL to Verilog converter tools
-- rev.: 1.1 june 18th, 2001. Changed PIOack generation. Avoid asserting PIOack continuously when IDEen = '0'
-- rev.: 1.2 june 26th, 2001. Changed dPIOreq generation. Core did not support wishbone burst accesses to ATA-device.
-- rev.: 1.3 july 11th, 2001. Changed PIOreq & PIOack generation (made them synchronous).
--
--
 
-- OCIDEC1 supports:
-- -Common Compatible timing access to all connected devices
211,11 → 211,10
gen_PIOgo: process(clk)
begin
if (clk'event and clk = '1') then
-- dPIOreq <= PIOreq;
dPIOreq <= PIOreq and not PIOack;
PIOgo <= (PIOreq and not dPIOreq) and IDEctrl_IDEen;
end if;
end process gen_PIOgo;
PIOgo <= (PIOreq and not dPIOreq) and IDEctrl_IDEen;
 
-- set Timing signals
T1 <= PIO_cmdport_T1;
233,7 → 232,11
port map (clk => clk, nReset => nReset, rst => rst, IORDY_en => IORDYen, T1 => T1, T2 => T2, T4 => T4, Teoc => Teoc,
go => PIOgo, we => PIOwe, oe => PIOoe, done => PIOdone, dstrb => dstrb, DIOR => PIOdior, DIOW => PIOdiow, IORDY => sIORDY);
 
PIOack <= PIOdone or (PIOreq and not IDEctrl_IDEen); -- acknowledge when done or when IDE not enabled (discard request)
-- generate acknowledge
gen_ack: process(clk)
begin
if (clk'event and clk = '1') then
PIOack <= PIOdone or (PIOreq and not IDEctrl_IDEen); -- acknowledge when done or when IDE not enabled (discard request)
end if;
end process gen_ack;
end architecture structural;
 
 
/trunk/vhdl/ocidec1/atahost.vhd
0,0 → 1,307
--
-- Project: AT Atachement interface
-- ATA-3 rev7B compliant
-- Author: Richard Herveille
-- Version: 1.0 Alpha version march 22nd, 2001
--
-- rev.: 1.0a april 12th, 2001. Removed references to records.vhd to make it compatible with freely available VHDL to Verilog converter tools
-- rev.: 1.1 june 18th, 2001. Changed wishbone address-input from (A4..A0) to (A6..A2)
-- rev.: 1.1a june 19th, 2001. Missed a reference to ADR_I(4). Simplified DAT_O output multiplexor.
--
 
-- DeviceType: OCIDEC-1: OpenCores IDE Controller type1
-- Features: PIO Compatible Timing
-- DeviceID: 0x01
-- RevNo : 0x00
 
--
-- Host signals:
-- Reset
-- DIOR- read strobe. The falling edge enables data from device onto DD. The rising edge latches data at the host.
-- DIOW- write strobe. The rising edge latches data from DD into the device.
-- DA(2:0) 3bit binary coded adress
-- CS0- select command block registers
-- CS1- select control block registers
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity atahost is
generic(
TWIDTH : natural := 8; -- counter width
 
-- PIO mode 0 settings (@100MHz clock)
PIO_mode0_T1 : natural := 6; -- 70ns
PIO_mode0_T2 : natural := 28; -- 290ns
PIO_mode0_T4 : natural := 2; -- 30ns
PIO_mode0_Teoc : natural := 23 -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
);
port(
-- WISHBONE SYSCON signals
CLK_I : in std_logic; -- master clock in
nReset : in std_logic := '1'; -- asynchronous active low reset
RST_I : in std_logic := '0'; -- synchronous active high reset
 
-- WISHBONE SLAVE signals
CYC_I : in std_logic; -- valid bus cycle input
STB_I : in std_logic; -- strobe/core select input
ACK_O : out std_logic; -- strobe acknowledge output
ERR_O : out std_logic; -- error output
ADR_I : in unsigned(6 downto 2); -- A6 = '1' ATA devices selected
-- A5 = '1' CS1- asserted, '0' CS0- asserted
-- A4..A2 ATA address lines
-- A6 = '0' ATA controller selected
DAT_I : in std_logic_vector(31 downto 0); -- Databus in
DAT_O : out std_logic_vector(31 downto 0); -- Databus out
SEL_I : in std_logic_vector(3 downto 0); -- Byte select signals
WE_I : in std_logic; -- Write enable input
INTA_O : out std_logic; -- interrupt request signal IDE0
 
-- ATA signals
RESETn : out std_logic;
DDi : in std_logic_vector(15 downto 0);
DDo : out std_logic_vector(15 downto 0);
DDoe : out std_logic;
DA : out unsigned(2 downto 0);
CS0n : out std_logic;
CS1n : out std_logic;
 
DIORn : out std_logic;
DIOWn : out std_logic;
IORDY : in std_logic;
INTRQ : in std_logic
);
end entity atahost;
 
architecture structural of atahost is
--
-- Device ID
--
constant DeviceId : unsigned(3 downto 0) := x"1";
constant RevisionNo : unsigned(3 downto 0) := x"0";
 
--
-- component declarations
--
component controller is
generic(
TWIDTH : natural := 8; -- counter width
 
-- PIO mode 0 settings (@100MHz clock)
PIO_mode0_T1 : natural := 6; -- 70ns
PIO_mode0_T2 : natural := 28; -- 290ns
PIO_mode0_T4 : natural := 2; -- 30ns
PIO_mode0_Teoc : natural := 23 -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
);
port(
clk : in std_logic; -- master clock in
nReset : in std_logic := '1'; -- asynchronous active low reset
rst : in std_logic := '0'; -- synchronous active high reset
irq : out std_logic; -- interrupt request signal
 
-- control / registers
IDEctrl_rst,
IDEctrl_IDEen : in std_logic;
 
-- PIO registers
PIO_cmdport_T1,
PIO_cmdport_T2,
PIO_cmdport_T4,
PIO_cmdport_Teoc : in unsigned(7 downto 0); -- PIO command timing
PIO_cmdport_IORDYen : in std_logic;
 
PIOreq : in std_logic; -- PIO transfer request
PIOack : buffer std_logic; -- PIO transfer ended
PIOa : in unsigned(3 downto 0); -- PIO address
PIOd : in std_logic_vector(15 downto 0); -- PIO data in
PIOq : out std_logic_vector(15 downto 0); -- PIO data out
PIOwe : in std_logic; -- PIO direction bit '1'=write, '0'=read
 
-- ATA signals
RESETn : out std_logic;
DDi : in std_logic_vector(15 downto 0);
DDo : out std_logic_vector(15 downto 0);
DDoe : out std_logic;
DA : out unsigned(2 downto 0);
CS0n : out std_logic;
CS1n : out std_logic;
 
DIORn : out std_logic;
DIOWn : out std_logic;
IORDY : in std_logic;
INTRQ : in std_logic
);
end component controller;
 
-- primary address decoder
signal CONsel, PIOsel : std_logic; -- controller select, IDE devices select
signal berr : std_logic; -- bus error
-- registers
signal IDEctrl_IDEen, IDEctrl_rst: std_logic;
signal PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc : unsigned(7 downto 0);
signal PIO_cmdport_IORDYen : std_logic;
signal CtrlReg : std_logic_vector(31 downto 0); -- control register
 
signal PIOack : std_logic;
signal PIOq : std_logic_vector(15 downto 0);
 
signal stat : std_logic_vector(31 downto 0);
 
signal irq : std_logic; -- ATA bus IRQ signal
 
begin
--
-- generate bus cycle / address decoder
--
gen_bc_dec: block
signal w_acc, dw_acc : std_logic; -- word access, double word access
signal store_pp_full : std_logic;
begin
-- word / double word
w_acc <= SEL_I(1) and SEL_I(0);
dw_acc <= SEL_I(3) and SEL_I(2) and SEL_I(1) and SEL_I(0);
 
-- bus error
berr <= (ADR_I(6) and not w_acc) or (not ADR_I(6) and not dw_acc);
 
-- PIO accesses at least 16bit wide
PIOsel <= CYC_I and STB_I and (ADR_I(6) and w_acc);
 
-- CON accesses only 32bit wide
CONsel <= CYC_I and STB_I and (not ADR_I(6) and dw_acc);
end block gen_bc_dec;
 
--
-- generate registers
--
register_block : block
signal sel_PIO_cmdport : std_logic; -- PIO timing registers
signal sel_ctrl, sel_stat : std_logic; -- control / status register
begin
-- generate register select signals
sel_ctrl <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and not ADR_I(3) and not ADR_I(2); -- 0x00
sel_stat <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and not ADR_I(3) and ADR_I(2); -- 0x01
sel_PIO_cmdport <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and ADR_I(3) and not ADR_I(2); -- 0x02
-- reserved 0x03-0x0f --
 
-- generate control register
gen_ctrl_reg: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
CtrlReg(31 downto 1) <= (others => '0');
CtrlReg(0) <= '1'; -- set reset bit
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
CtrlReg(31 downto 1) <= (others => '0');
CtrlReg(0) <= '1'; -- set reset bit
elsif (sel_ctrl = '1') then
CtrlReg <= DAT_I;
end if;
end if;
end process gen_ctrl_reg;
-- assign bits
IDEctrl_IDEen <= CtrlReg(7);
PIO_cmdport_IORDYen <= CtrlReg(1);
IDEctrl_rst <= CtrlReg(0);
 
-- generate status register clearable bits
gen_stat_reg: block
signal dirq, int : std_logic;
begin
gen_irq: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
int <= '0';
dirq <= '0';
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
int <= '0';
dirq <= '0';
else
int <= (int or (irq and not dirq)) and not (sel_stat and not DAT_I(0));
dirq <= irq;
end if;
end if;
end process gen_irq;
 
gen_stat: process(int)
begin
stat(31 downto 0) <= (others => '0'); -- clear all bits (read unused bits as '0')
 
stat(31 downto 28) <= std_logic_vector(DeviceId); -- set Device ID
stat(27 downto 24) <= std_logic_vector(RevisionNo); -- set revision number
-- stat(7) <= PIOtip;
-- PIOtip is only asserted during a PIO transfer (No shit! :-) )
-- Since it is impossible to read the status register and access the PIO registers at the same time
-- this bit is useless (besides using-up resources)
stat(0) <= int;
end process;
end block gen_stat_reg;
 
-- generate PIO compatible / command-port timing register
gen_PIO_cmdport_reg: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
PIO_cmdport_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_cmdport_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_cmdport_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_cmdport_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
PIO_cmdport_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_cmdport_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_cmdport_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_cmdport_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (sel_PIO_cmdport = '1') then
PIO_cmdport_T1 <= unsigned(DAT_I( 7 downto 0));
PIO_cmdport_T2 <= unsigned(DAT_I(15 downto 8));
PIO_cmdport_T4 <= unsigned(DAT_I(23 downto 16));
PIO_cmdport_Teoc <= unsigned(DAT_I(31 downto 24));
end if;
end if;
end process gen_PIO_cmdport_reg;
end block register_block;
 
--
-- hookup controller section
--
u1: controller
generic map(TWIDTH => TWIDTH, PIO_mode0_T1 => PIO_mode0_T1, PIO_mode0_T2 => PIO_mode0_T2, PIO_mode0_T4 => PIO_mode0_T4, PIO_mode0_Teoc => PIO_mode0_Teoc)
port map(CLK_I, nRESET, RST_I, irq, IDEctrl_rst, IDEctrl_IDEen, PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc, PIO_cmdport_IORDYen,
PIOsel, PIOack, ADR_I(5 downto 2), DAT_I(15 downto 0), PIOq, WE_I, RESETn, DDi, DDo, DDoe, DA, CS0n, CS1n, DIORn, DIOWn, IORDY, INTRQ);
 
--
-- generate WISHBONE interconnect signals
--
gen_WB_sigs: block
signal Q : std_logic_vector(31 downto 0);
begin
-- generate acknowledge signal
ACK_O <= PIOack or CONsel;
 
-- generate error signal
ERR_O <= CYC_I and STB_I and berr;
 
-- generate interrupt signal
INTA_O <= stat(0);
-- generate output multiplexor
with ADR_I(5 downto 2) select
Q <= CtrlReg when "0000", -- control register
stat when "0001", -- status register
std_logic_vector(PIO_cmdport_Teoc & PIO_cmdport_T4 & PIO_cmdport_T2 & PIO_cmdport_T1) when "0010",
(others => '0') when others;
 
DAT_O <= (x"0000" & PIOq) when (ADR_I(6) = '1') else Q;
 
end block gen_WB_sigs;
 
end architecture structural;
 
 
 
 
 
/trunk/vhdl/ocidec1/revision_history.txt
38,3 → 38,11
- Change PIOack from "out" to "buffer" (controller.vhd + ata.vhd)
-----------------------------
 
-----------------------------
Revision: 1.3
Date: July 11th, 2001
Author: Richard Herveille
- renamed 'ata.vhd' to 'atahost.vhd'
- Changed PIOreq & PIOack generation (controller.vhd); made them synchronous
- Changed 'go' & 'igo' generation (pio_tctrl.vhdl).
-----------------------------
/trunk/vhdl/ocidec2/pio_tctrl.vhd
2,7 → 2,8
-- file: pio_tctrl.vhd
-- description: PIO mode timing controller for ATA controller
-- author : Richard Herveille
-- rev.: 1.0 march 7th, 2001
-- rev.: 1.0 march 7th, 2001. Initial release
-- rev.: 1.1 July 11th, 2001. Changed 'igo' & 'hold_go' signal generation.
--
 
--
126,11 → 127,11
hold_go <= '0';
else
busy <= (igo or busy) and not Teoc_done;
hold_go <= go or (hold_go and busy);
hold_go <= (go or (hold_go and busy)) and not igo;
end if;
end if;
end process;
igo <= hold_go and not busy;
igo <= (go or hold_go) and not busy;
 
-- 1) hookup T1 counter
t1_cnt : ro_cnt generic map (SIZE => TWIDTH)
205,3 → 206,9
 
 
 
 
 
 
 
 
 
/trunk/vhdl/ocidec2/controller.vhd
6,6 → 6,7
-- rev.: 1.0a april 12th, 2001 Removed references to records.vhd
-- rev.: 1.1 june 18th, 2001. Changed PIOack generation. Avoid asserting PIOack continuously when IDEen = '0'
-- rev.: 1.2 june 26th, 2001. Changed dPIOreq generation. Core did not support wishbone burst accesses to ATA-device.
-- rev.: 1.3 july 11th, 2001. Changed PIOreq & PIOack generation (made them synchronous).
 
--
-- OCIDEC2 supports:
237,10 → 238,9
begin
if (clk'event and clk = '1') then
dPIOreq <= PIOreq and not PIOack;
PIOgo <= (PIOreq and not dPIOreq) and IDEctrl_IDEen;
end if;
end process gen_PIOgo;
PIOgo <= (PIOreq and not dPIOreq) and IDEctrl_IDEen;
 
--
-- Hookup PIO access controller
--
250,5 → 250,11
dport0_T1, dport0_T2, dport0_T4, dport0_Teoc, dport0_IORDYen, dport1_T1, dport1_T2, dport1_T4, dport1_Teoc, dport1_IORDYen,
SelDev, PIOgo, PIOdone, PIOwe, PIOa, PIOq, DDi, PIOoe, PIOdior, PIOdiow, sIORDY);
 
PIOack <= PIOdone or (PIOreq and not IDEctrl_IDEen); -- acknowledge when done or when IDE not enabled (discard request)
-- generate acknowledge
gen_ack: process(clk)
begin
if (clk'event and clk = '1') then
PIOack <= PIOdone or (PIOreq and not IDEctrl_IDEen); -- acknowledge when done or when IDE not enabled (discard request)
end if;
end process gen_ack;
end architecture structural;
/trunk/vhdl/ocidec2/atahost.vhd
0,0 → 1,386
--
-- Project: AT Atachement interface
-- ATA-3 rev7B compliant
-- Author: Richard Herveille
--
-- rev.: 1.0a Removed references to records.vhd, make core compatible with VHDL to Verilog translator tools
-- rev.: 1.1 june 18th, 2001. Changed wishbone address input from ADR_I(4 downto 0) to ADR_I(6 downto 2)
-- rev.: 1.1a june 19th, 2001. Simplified DAT_O output multiplexor.
 
--
-- DeviceType: OCIDEC-2: OpenCores IDE Controller type2
-- Features: PIO Compatible Timing, PIO Fast Timing 0/1
-- DeviceID: 0x02
-- RevNo : 0x00
 
--
-- Host signals:
-- Reset
-- DIOR- read strobe. The falling edge enables data from device onto DD. The rising edge latches data at the host.
-- DIOW- write strobe. The rising edge latches data from DD into the device.
-- DA(2:0) 3bit binary coded adress
-- CS0- select command block registers
-- CS1- select control block registers
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity atahost is
generic(
TWIDTH : natural := 8; -- counter width
 
-- PIO mode 0 settings (@100MHz clock)
PIO_mode0_T1 : natural := 6; -- 70ns
PIO_mode0_T2 : natural := 28; -- 290ns
PIO_mode0_T4 : natural := 2; -- 30ns
PIO_mode0_Teoc : natural := 23 -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
);
port(
-- WISHBONE SYSCON signals
CLK_I : in std_logic; -- master clock in
nReset : in std_logic := '1'; -- asynchronous active low reset
RST_I : in std_logic := '0'; -- synchronous active high reset
 
-- WISHBONE SLAVE signals
CYC_I : in std_logic; -- valid bus cycle input
STB_I : in std_logic; -- strobe/core select input
ACK_O : out std_logic; -- strobe acknowledge output
ERR_O : out std_logic; -- error output
ADR_I : in unsigned(6 downto 2); -- A6 = '1' ATA devices selected
-- A5 = '1' CS1- asserted, '0' CS0- asserted
-- A4..A2 ATA address lines
-- A6 = '0' ATA controller selected
DAT_I : in std_logic_vector(31 downto 0); -- Databus in
DAT_O : out std_logic_vector(31 downto 0); -- Databus out
SEL_I : in std_logic_vector(3 downto 0); -- Byte select signals
WE_I : in std_logic; -- Write enable input
INTA_O : out std_logic; -- interrupt request signal IDE0
 
-- ATA signals
RESETn : out std_logic;
DDi : in std_logic_vector(15 downto 0);
DDo : out std_logic_vector(15 downto 0);
DDoe : out std_logic;
DA : out unsigned(2 downto 0);
CS0n : out std_logic;
CS1n : out std_logic;
 
DIORn : out std_logic;
DIOWn : out std_logic;
IORDY : in std_logic;
INTRQ : in std_logic
);
end entity atahost;
 
architecture structural of atahost is
--
-- Device ID
--
constant DeviceId : unsigned(3 downto 0) := x"2";
constant RevisionNo : unsigned(3 downto 0) := x"0";
 
--
-- component declarations
--
component controller is
generic(
TWIDTH : natural := 8; -- counter width
 
-- PIO mode 0 settings (@100MHz clock)
PIO_mode0_T1 : natural := 6; -- 70ns
PIO_mode0_T2 : natural := 28; -- 290ns
PIO_mode0_T4 : natural := 2; -- 30ns
PIO_mode0_Teoc : natural := 23 -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
);
port(
clk : in std_logic; -- master clock in
nReset : in std_logic := '1'; -- asynchronous active low reset
rst : in std_logic := '0'; -- synchronous active high reset
irq : out std_logic; -- interrupt request signal
 
-- control / registers
IDEctrl_rst,
IDEctrl_IDEen,
IDEctrl_FATR0,
IDEctrl_FATR1 : in std_logic;
 
-- PIO registers
cmdport_T1,
cmdport_T2,
cmdport_T4,
cmdport_Teoc : in unsigned(7 downto 0);
cmdport_IORDYen : in std_logic; -- PIO command port / non-fast timing
 
dport0_T1,
dport0_T2,
dport0_T4,
dport0_Teoc : in unsigned(7 downto 0);
dport0_IORDYen : in std_logic; -- PIO mode data-port / fast timing device 0
 
dport1_T1,
dport1_T2,
dport1_T4,
dport1_Teoc : in unsigned(7 downto 0);
dport1_IORDYen : in std_logic; -- PIO mode data-port / fast timing device 1
 
PIOreq : in std_logic; -- PIO transfer request
PIOack : buffer std_logic; -- PIO transfer ended
PIOa : in unsigned(3 downto 0); -- PIO address
PIOd : in std_logic_vector(15 downto 0); -- PIO data in
PIOq : out std_logic_vector(15 downto 0); -- PIO data out
PIOwe : in std_logic; -- PIO direction bit '1'=write, '0'=read
 
-- ATA signals
RESETn : out std_logic;
DDi : in std_logic_vector(15 downto 0);
DDo : out std_logic_vector(15 downto 0);
DDoe : out std_logic;
DA : out unsigned(2 downto 0);
CS0n : out std_logic;
CS1n : out std_logic;
 
DIORn : out std_logic;
DIOWn : out std_logic;
IORDY : in std_logic;
INTRQ : in std_logic
);
end component controller;
 
-- primary address decoder
signal CONsel, PIOsel : std_logic; -- controller select, IDE devices select
signal berr : std_logic; -- bus error
-- registers
-- control register
signal IDEctrl_rst, IDEctrl_IDEen, IDEctrl_FATR0, IDEctrl_FATR1 : std_logic;
-- compatible mode timing register
signal PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc : unsigned(7 downto 0);
signal PIO_cmdport_IORDYen : std_logic;
-- data port0 timing register
signal PIO_dport0_T1, PIO_dport0_T2, PIO_dport0_T4, PIO_dport0_Teoc : unsigned(7 downto 0);
signal PIO_dport0_IORDYen : std_logic;
-- data port1 timing register
signal PIO_dport1_T1, PIO_dport1_T2, PIO_dport1_T4, PIO_dport1_Teoc : unsigned(7 downto 0);
signal PIO_dport1_IORDYen : std_logic;
 
signal CtrlReg : std_logic_vector(31 downto 0); -- control register
 
signal PIOack : std_logic;
signal PIOq : std_logic_vector(15 downto 0);
 
signal stat : std_logic_vector(31 downto 0);
 
signal irq : std_logic; -- ATA bus IRQ signal
 
begin
--
-- generate bus cycle / address decoder
--
gen_bc_dec: block
signal w_acc, dw_acc : std_logic; -- word access, double word access
signal store_pp_full : std_logic;
begin
-- word / double word
w_acc <= SEL_I(1) and SEL_I(0);
dw_acc <= SEL_I(3) and SEL_I(2) and SEL_I(1) and SEL_I(0);
 
-- bus error
berr <= (ADR_I(6) and not w_acc) or (not ADR_I(6) and not dw_acc);
 
-- PIO accesses at least 16bit wide
PIOsel <= CYC_I and STB_I and (ADR_I(6) and w_acc);
 
-- CON accesses only 32bit wide
CONsel <= CYC_I and STB_I and (not ADR_I(6) and dw_acc);
end block gen_bc_dec;
 
--
-- generate registers
--
register_block : block
signal sel_PIO_cmdport, sel_PIO_dport0, sel_PIO_dport1 : std_logic; -- PIO timing registers
signal sel_ctrl, sel_stat : std_logic; -- control / status register
begin
-- generate register select signals
sel_ctrl <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and not ADR_I(3) and not ADR_I(2); -- 0x00
sel_stat <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and not ADR_I(3) and ADR_I(2); -- 0x04
sel_PIO_cmdport <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and ADR_I(3) and not ADR_I(2); -- 0x08
sel_PIO_dport0 <= CONsel and WE_I and not ADR_I(5) and not ADR_I(4) and ADR_I(3) and ADR_I(2); -- 0x0C
sel_PIO_dport1 <= CONsel and WE_I and not ADR_I(5) and ADR_I(4) and not ADR_I(3) and not ADR_I(2); -- 0x10
-- reserved 0x14-0x3C --
 
-- generate control register
gen_ctrl_reg: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
CtrlReg(31 downto 1) <= (others => '0');
CtrlReg(0) <= '1'; -- set reset bit
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
CtrlReg(31 downto 1) <= (others => '0');
CtrlReg(0) <= '1'; -- set reset bit
elsif (sel_ctrl = '1') then
CtrlReg <= DAT_I;
end if;
end if;
end process gen_ctrl_reg;
-- assign bits
IDEctrl_IDEen <= CtrlReg(7);
IDEctrl_FATR1 <= CtrlReg(6);
IDEctrl_FATR0 <= CtrlReg(5);
PIO_dport1_IORDYen <= CtrlReg(3);
PIO_dport0_IORDYen <= CtrlReg(2);
PIO_cmdport_IORDYen <= CtrlReg(1);
IDEctrl_rst <= CtrlReg(0);
 
-- generate status register clearable bits
gen_stat_reg: block
signal dirq, int : std_logic;
begin
gen_irq: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
int <= '0';
dirq <= '0';
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
int <= '0';
dirq <= '0';
else
int <= (int or (irq and not dirq)) and not (sel_stat and not DAT_I(0));
dirq <= irq;
end if;
end if;
end process gen_irq;
 
gen_stat: process(int)
begin
stat(31 downto 0) <= (others => '0'); -- clear all bits (read unused bits as '0')
 
stat(31 downto 28) <= std_logic_vector(DeviceId); -- set Device ID
stat(27 downto 24) <= std_logic_vector(RevisionNo); -- set revision number
-- stat(7) <= PIOtip;
-- PIOtip is only asserted during a PIO transfer (No shit! ;)
-- Since it is impossible to read the status register and access the PIO registers at the same time
-- this bit is useless (besides using-up resources)
stat(0) <= int;
end process;
end block gen_stat_reg;
 
-- generate PIO compatible / command-port timing register
gen_PIO_cmdport_reg: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
PIO_cmdport_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_cmdport_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_cmdport_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_cmdport_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
PIO_cmdport_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_cmdport_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_cmdport_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_cmdport_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (sel_PIO_cmdport = '1') then
PIO_cmdport_T1 <= unsigned(DAT_I( 7 downto 0));
PIO_cmdport_T2 <= unsigned(DAT_I(15 downto 8));
PIO_cmdport_T4 <= unsigned(DAT_I(23 downto 16));
PIO_cmdport_Teoc <= unsigned(DAT_I(31 downto 24));
end if;
end if;
end process gen_PIO_cmdport_reg;
 
-- generate PIO device0 timing register
gen_PIO_dport0_reg: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
PIO_dport0_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_dport0_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_dport0_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_dport0_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
PIO_dport0_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_dport0_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_dport0_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_dport0_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (sel_PIO_dport0 = '1') then
PIO_dport0_T1 <= unsigned(DAT_I( 7 downto 0));
PIO_dport0_T2 <= unsigned(DAT_I(15 downto 8));
PIO_dport0_T4 <= unsigned(DAT_I(23 downto 16));
PIO_dport0_Teoc <= unsigned(DAT_I(31 downto 24));
end if;
end if;
end process gen_PIO_dport0_reg;
 
-- generate PIO device1 timing register
gen_PIO_dport1_reg: process(CLK_I, nRESET)
begin
if (nRESET = '0') then
PIO_dport1_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_dport1_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_dport1_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_dport1_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (CLK_I'event and CLK_I = '1') then
if (RST_I = '1') then
PIO_dport1_T1 <= conv_unsigned(PIO_mode0_T1, TWIDTH);
PIO_dport1_T2 <= conv_unsigned(PIO_mode0_T2, TWIDTH);
PIO_dport1_T4 <= conv_unsigned(PIO_mode0_T4, TWIDTH);
PIO_dport1_Teoc <= conv_unsigned(PIO_mode0_Teoc, TWIDTH);
elsif (sel_PIO_dport1 = '1') then
PIO_dport1_T1 <= unsigned(DAT_I( 7 downto 0));
PIO_dport1_T2 <= unsigned(DAT_I(15 downto 8));
PIO_dport1_T4 <= unsigned(DAT_I(23 downto 16));
PIO_dport1_Teoc <= unsigned(DAT_I(31 downto 24));
end if;
end if;
end process gen_PIO_dport1_reg;
 
end block register_block;
 
--
-- hookup controller section
--
u1: controller
generic map(TWIDTH => TWIDTH, PIO_mode0_T1 => PIO_mode0_T1, PIO_mode0_T2 => PIO_mode0_T2, PIO_mode0_T4 => PIO_mode0_T4, PIO_mode0_Teoc => PIO_mode0_Teoc)
port map(CLK_I, nRESET, RST_I, irq, IDEctrl_rst, IDEctrl_IDEen, IDEctrl_FATR0, IDEctrl_FATR1,
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,
PIOsel, PIOack, ADR_I(5 downto 2), DAT_I(15 downto 0), PIOq, WE_I,
RESETn, DDi, DDo, DDoe, DA, CS0n, CS1n, DIORn, DIOWn, IORDY, INTRQ);
 
--
-- generate WISHBONE interconnect signals
--
gen_WB_sigs: block
signal Q : std_logic_vector(31 downto 0);
begin
-- generate acknowledge signal
ACK_O <= PIOack or CONsel;
 
-- generate error signal
ERR_O <= CYC_I and STB_I and berr;
 
-- generate interrupt signal
INTA_O <= stat(0);
-- generate output multiplexor
with ADR_I(5 downto 2) select
Q <= CtrlReg when "0000", -- control register
stat when "0001", -- status register
std_logic_vector(PIO_cmdport_Teoc & PIO_cmdport_T4 & PIO_cmdport_T2 & PIO_cmdport_T1) when "0010",
std_logic_vector(PIO_dport0_Teoc & PIO_dport0_T4 & PIO_dport0_T2 & PIO_dport0_T1) when "0011",
std_logic_vector(PIO_dport1_Teoc & PIO_dport1_T4 & PIO_dport1_T2 & PIO_dport1_T1) when "0100",
(others => '0') when others;
 
DAT_O <= (x"0000" & PIOq) when (ADR_I(6) = '1') else Q;
 
end block gen_WB_sigs;
 
end architecture structural;
 
 
 
/trunk/vhdl/ocidec2/revision_history.txt
36,3 → 36,12
- Changed dPIOreq generation (controller.vhd). Wishbone burst accesses to ata device were not handled correctly
- Change PIOack from "out" to "buffer" (controller.vhd + ata.vhd)
-----------------------------
 
-----------------------------
Revision: 1.3
Date: July 11th, 2001
Author: Richard Herveille
- renamed 'ata.vhd' to 'atahost.vhd'
- Changed PIOreq & PIOack generation (controller.vhd); made them synchronous
- Changed 'go' & 'igo' generation (pio_tctrl.vhdl).
-----------------------------

powered by: WebSVN 2.1.0

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