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 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/verilog/ocidec-1/counter.v
0,0 → 1,103
//
// Counter.vhd, contains 1) run-once down-counter 2) general purpose up-down riple-carry counter
//
// Author: Richard Herveille
// Rev. 1.0 June 27th, 2001. Initial Verilog release
//
//
 
 
/////////////////////////////
// general purpose counter //
/////////////////////////////
 
module ud_cnt (clk, nReset, rst, cnt_en, ud, nld, d, q, resd, rci, rco);
// parameter declaration
parameter SIZE = 8;
// inputs & outputs
input clk; // master clock
input nReset; // asynchronous active low reset
input rst; // synchronous active high reset
input cnt_en; // count enable
input ud; // up/not down
input nld; // synchronous active low load
input [SIZE-1:0] d; // load counter value
output [SIZE-1:0] q; // current counter value
input [SIZE-1:0] resd; // initial data after/during reset
input rci; // carry input
output rco; // carry output
 
// variable declarations
reg [SIZE-1:0] Qi; // intermediate value
wire [SIZE:0] val; // carry+result
 
//
// Module body
//
 
assign val = ud ? ( {1'b0, Qi} + rci) : ( {1'b0, Qi} - rci);
 
always@(posedge clk or negedge nReset)
begin
if (~nReset)
Qi <= resd;
else if (rst)
Qi <= resd;
else if (~nld)
Qi <= d;
else if (cnt_en)
Qi <= val[SIZE-1:0];
end
 
// assign outputs
assign q = Qi;
assign rco = val[SIZE];
endmodule
 
 
///////////////////////////
// run-once down-counter //
///////////////////////////
 
// counts D+1 cycles before generating 'DONE'
 
module ro_cnt (clk, nReset, rst, cnt_en, go, done, d, q, id);
// parameter declaration
parameter SIZE = 8;
// inputs & outputs
input clk; // master clock
input nReset; // asynchronous active low reset
input rst; // synchronous active high reset
input cnt_en; // count enable
input go; // load counter and start sequence
output done; // done counting
input [SIZE-1:0] d; // load counter value
output [SIZE-1:0] q; // current counter value
input [SIZE-1:0] id; // initial data after reset
 
// variable declarations
reg rci, rco;
wire nld;
 
//
// module body
//
 
always@(posedge clk or negedge nReset)
if (~nReset)
rci <= 1'b0;
else if (rst)
rci <= 1'b0;
else if (cnt_en)
rci <= (go | rci) & !rco;
 
assign nld = !go;
 
// hookup counter
ud_cnt #(SIZE) cnt (.clk(clk), .nReset(nReset), .rst(rst), .cnt_en(cnt_en), .nld(nld), .d(d), .q(q),
.resd(id), .rci(rci), .rco(rco));
 
// assign outputs
assign done = rco;
endmodule
 
/trunk/verilog/ocidec-1/pio_tctrl.v
0,0 → 1,175
//
// file: pio_tctrl.vhd
// description: PIO mode timing controller for ATA controller
// author : Richard Herveille
// rev.: 1.0 march 7th, 2001
//
 
//
///////////////////////////
// PIO Timing controller //
///////////////////////////
//
 
//
// Timing PIO mode transfers
//--------------------------------------------
// T0: cycle time
// T1: address valid to DIOR-/DIOW-
// T2: DIOR-/DIOW- pulse width
// T2i: DIOR-/DIOW- recovery time
// T3: DIOW- data setup
// T4: DIOW- data hold
// T5: DIOR- data setup
// T6: DIOR- data hold
// T9: address hold from DIOR-/DIOW- negated
// Trd: Read data valid to IORDY asserted
// Ta: IORDY setup time
// Tb: IORDY pulse width
//
// Transfer sequence
//--------------------------------
// 1) set address (DA, CS0-, CS1-)
// 2) wait for T1
// 3) assert DIOR-/DIOW-
// when write action present Data (timing spec. T3 always honored), enable output enable-signal
// 4) wait for T2
// 5) check IORDY
// when not IORDY goto 5
// when IORDY negate DIOW-/DIOR-, latch data (if read action)
// when write, hold data for T4, disable output-enable signal
// 6) wait end_of_cycle_time. This is T2i or T9 or (T0-T1-T2) whichever takes the longest
// 7) start new cycle
 
module pio_tctrl(clk, nReset, rst, IORDY_en, T1, T2, T4, Teoc, go, we, oe, done, dstrb, DIOR, DIOW, IORDY);
// parameter declarations
parameter TWIDTH = 8;
parameter PIO_MODE0_T1 = 6; // 70ns
parameter PIO_MODE0_T2 = 28; // 290ns
parameter PIO_MODE0_T4 = 2; // 30ns
parameter PIO_MODE0_Teoc = 23; // 240ns
// inputs & outputs
input clk; // master clock
input nReset; // asynchronous active low reset
input rst; // synchronous active high reset
// timing & control register settings
input IORDY_en; // use IORDY (or not)
input [TWIDTH-1:0] T1; // T1 time (in clk-ticks)
input [TWIDTH-1:0] T2; // T1 time (in clk-ticks)
input [TWIDTH-1:0] T4; // T1 time (in clk-ticks)
input [TWIDTH-1:0] Teoc; // T1 time (in clk-ticks)
 
// control signals
input go; // PIO controller selected (strobe signal)
input we; // write enable signal. 1'b0 == read, 1'b1 == write
 
// return signals
output oe; // output enable signal
reg oe;
output done; // finished cycle
output dstrb; // data strobe, latch data (during read)
reg dstrb;
 
// ata signals
output DIOR; // IOread signal, active high
reg DIOR;
output DIOW; // IOwrite signal, active high
reg DIOW;
input IORDY; // IOrDY signal
 
 
//
// constant declarations
//
// PIO mode 0 settings (@100MHz clock)
parameter [TWIDTH-1:0] T1_m0 = PIO_MODE0_T1;
parameter [TWIDTH-1:0] T2_m0 = PIO_MODE0_T2;
parameter [TWIDTH-1:0] T4_m0 = PIO_MODE0_T4;
parameter [TWIDTH-1:0] Teoc_m0 = PIO_MODE0_Teoc;
 
//
// variable declaration
//
reg busy, hold_go;
wire igo;
wire T1done, T2done, T4done, Teoc_done, IORDY_done;
reg hT2done;
 
//
// module body
//
 
// generate internal go strobe
// strecht go until ready for new cycle
always@(posedge clk or negedge nReset)
if (~nReset)
begin
busy <= 1'b0;
hold_go <= 1'b0;
end
else if (rst)
begin
busy <= 1'b0;
hold_go <= 1'b0;
end
else
begin
busy <= (igo | busy) & !Teoc_done;
hold_go <= go | (hold_go & busy);
end
 
assign igo = hold_go & !busy;
 
// 1) hookup T1 counter
ro_cnt #(TWIDTH) t1_cnt(.clk(clk), .nReset(nReset), .rst(rst), .go(igo), .d(T1), .id(T1_m0), .done(T1done));
 
// 2) set (and reset) DIOR-/DIOW-, set output-enable when writing to device
always@(posedge clk or negedge nReset)
if (~nReset)
begin
DIOR <= 1'b0;
DIOW <= 1'b0;
oe <= 1'b0;
end
else if (rst)
begin
DIOR <= 1'b0;
DIOW <= 1'b0;
oe <= 1'b0;
end
else
begin
DIOR <= (!we & T1done) | (DIOR & !IORDY_done);
DIOW <= ( we & T1done) | (DIOW & !IORDY_done);
oe <= ( (we & igo) | oe) & !T4done; // negate oe when t4-done
end
 
// 3) hookup T2 counter
ro_cnt #(TWIDTH) t2_cnt(.clk(clk), .nReset(nReset), .rst(rst), .go(T1done), .d(T2), .id(T2_m0), .done(T2done));
 
// 4) check IORDY (if used), generate release_DIOR-/DIOW- signal (ie negate DIOR-/DIOW-)
// hold T2done
always@(posedge clk or negedge nReset)
if (~nReset)
hT2done <= 1'b0;
else if (rst)
hT2done <= 1'b0;
else
hT2done <= (T2done | hT2done) & !IORDY_done;
 
assign IORDY_done = (T2done | hT2done) & (IORDY | !IORDY_en);
 
// generate datastrobe, capture data at rising DIOR- edge
always@(posedge clk)
dstrb <= IORDY_done;
 
// hookup data hold counter
ro_cnt #(TWIDTH) dhold_cnt(.clk(clk), .nReset(nReset), .rst(rst), .go(IORDY_done), .d(T4), .id(T4_m0), .done(T4done));
assign done = T4done; // placing done here provides the fastest return possible,
// while still guaranteeing data and address hold-times
 
// 5) hookup end_of_cycle counter
ro_cnt #(TWIDTH) eoc_cnt(.clk(clk), .nReset(nReset), .rst(rst), .go(IORDY_done), .d(Teoc), .id(Teoc_m0), .done(Teoc_done));
endmodule
/trunk/verilog/ocidec-1/controller.v
0,0 → 1,186
//
// file: controller.vhd
// description: OCIDEC1 OpenCores IDE controller type-1
// author : Richard Herveille
// rev.: 1.0 june 28th, 2001. Initial Verilog release
//
 
// OCIDEC1 supports:
// -Common Compatible timing access to all connected devices
//
 
module controller (clk, nReset, rst, irq, IDEctrl_rst, IDEctrl_IDEen,
PIO_cmdport_T1, PIO_cmdport_T2, PIO_cmdport_T4, PIO_cmdport_Teoc, PIO_cmdport_IORDYen,
PIOreq, PIOack, PIOa, PIOd, PIOq, PIOwe,
RESETn, DDi, DDo, DDoe, DA, CS0n, CS1n, DIORn, DIOWn, IORDY, INTRQ);
//
// parameter declarations
//
parameter TWIDTH = 8; // counter width
// PIO mode 0 timing settings @100MHz master 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
//
input clk; //master clock
input nReset; // asynchronous active low reset
input rst; // synchronous active high reset
output irq; // interrupt request signal
reg irq;
// control bits
input IDEctrl_rst;
input IDEctrl_IDEen;
 
// PIO timing registers
input [7:0] PIO_cmdport_T1;
input [7:0] PIO_cmdport_T2;
input [7:0] PIO_cmdport_T4;
input [7:0] PIO_cmdport_Teoc;
input PIO_cmdport_IORDYen;
 
// PIO control signals
input PIOreq; // PIO transfer request
output PIOack; // PIO transfer ended
input [ 3:0] PIOa; // PIO address
input [15:0] PIOd; // PIO data in
output [15:0] PIOq; // PIO data out
input PIOwe; // PIO direction bit. 1'b1==write, 1'b0==read
 
reg [15:0] PIOq;
 
// 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;
 
reg RESETn;
reg [15:0] DDo;
reg DDoe;
reg [ 2:0] DA;
reg CS0n;
reg CS1n;
reg DIORn;
reg DIOWn;
 
//
// Variable declarations
//
 
reg dPIOreq;
wire PIOgo; // start PIO timing controller
wire PIOdone; // PIO timing controller done
 
// PIO signals
wire PIOdior, PIOdiow;
wire PIOoe;
 
// Timing settings
wire dstrb;
wire [TWIDTH-1:0] T1, T2, T4, Teoc;
wire IORDYen;
 
// synchronized ATA inputs
reg sIORDY;
 
//
// Module body
//
 
 
// synchronize incoming signals
always
begin : synch_incoming
reg cIORDY; // capture IORDY
reg cINTRQ; // capture INTRQ
@(posedge clk)
begin
cIORDY <= IORDY;
cINTRQ <= INTRQ;
 
sIORDY <= cIORDY;
irq <= cINTRQ;
end
end
 
// generate ATA signals
always@(posedge clk or negedge nReset)
if (~nReset)
begin
RESETn <= 1'b0;
DIORn <= 1'b1;
DIOWn <= 1'b1;
DA <= 0; // ????
CS0n <= 1'b1;
CS1n <= 1'b1;
DDo <= 0;
DDoe <= 1'b0;
end
else if (rst)
begin
RESETn <= 1'b0;
DIORn <= 1'b1;
DIOWn <= 1'b1;
DA <= 0; // ????
CS0n <= 1'b1;
CS1n <= 1'b1;
DDo <= 0;
DDoe <= 1'b0;
end
else
begin
RESETn <= !IDEctrl_rst;
DA <= PIOa[2:0];
CS0n <= !( !PIOa[3] & PIOreq); // CS0 asserted when A(3) = '0'
CS1n <= !( PIOa[3] & PIOreq); // CS1 asserted when A(3) = '1'
 
DDo <= PIOd;
DDoe <= PIOoe;
DIORn <= !PIOdior;
DIOWn <= !PIOdiow;
end
 
 
//
//////////////////////////
// PIO transfer control //
//////////////////////////
//
// capture ATA data for PIO access
always@(posedge clk)
if (dstrb)
PIOq <= DDi;
 
// generate PIOgo signal
always@(posedge clk)
dPIOreq <= PIOreq & !PIOack;
 
assign PIOgo = (PIOreq & !dPIOreq) & IDEctrl_IDEen;
 
// set Timing signals
assign T1 = PIO_cmdport_T1;
assign T2 = PIO_cmdport_T2;
assign T4 = PIO_cmdport_T4;
assign Teoc = PIO_cmdport_Teoc;
assign IORDYen = PIO_cmdport_IORDYen;
 
// hookup timing controller
PIO_tctrl #(TWIDTH, PIO_mode0_T1, PIO_mode0_T2, PIO_mode0_T4, PIO_mode0_Teoc)
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)
endmodule
/trunk/verilog/ocidec-1/ata.v
0,0 → 1,229
//
// Project: AT Atachement interface
// ATA-3 rev7B compliant
// Author: Richard Herveille
// rev.: 1.0 june 29th, 2001. Initial Verilog release
//
 
// 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
 
 
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
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
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[5:2] 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
 

powered by: WebSVN 2.1.0

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