fixed eol-style
This commit is contained in:
198
rtl/ide.v
198
rtl/ide.v
@@ -1,99 +1,99 @@
|
||||
//
|
||||
// ide.v
|
||||
// simple state machine to do proper read & write cycles to ATA IDE device
|
||||
//
|
||||
|
||||
module ide(clk, reset, ata_rd, ata_wr, ata_addr, ata_in, ata_out, ata_done,
|
||||
ide_data_bus, ide_dior, ide_diow, ide_cs, ide_da);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
|
||||
input ata_rd;
|
||||
input ata_wr;
|
||||
input [4:0] ata_addr;
|
||||
input [15:0] ata_in;
|
||||
output [15:0] ata_out;
|
||||
reg [15:0] ata_out;
|
||||
output ata_done;
|
||||
|
||||
inout [15:0] ide_data_bus;
|
||||
output ide_dior;
|
||||
output ide_diow;
|
||||
output [1:0] ide_cs;
|
||||
output [2:0] ide_da;
|
||||
|
||||
|
||||
reg [2:0] ata_state;
|
||||
|
||||
parameter [2:0]
|
||||
idle = 3'd0,
|
||||
s0 = 3'd1,
|
||||
s1 = 3'd2,
|
||||
s2 = 3'd3,
|
||||
s3 = 3'd4,
|
||||
s4 = 3'd5;
|
||||
|
||||
wire assert_cs;
|
||||
wire assert_rw;
|
||||
|
||||
reg [2:0] ata_state_next;
|
||||
|
||||
|
||||
// if write, drive ide_bus
|
||||
assign ide_data_bus = (ata_wr && (ata_state == s0 ||
|
||||
ata_state == s1 ||
|
||||
ata_state == s2 ||
|
||||
ata_state == s3)) ? ata_in : 16'bz;
|
||||
|
||||
// assert cs & da during r/w cycle
|
||||
assign assert_cs = (ata_rd || ata_wr) && ata_state != s4;
|
||||
|
||||
assign ide_cs = assert_cs ? ata_addr[4:3] : 2'b11;
|
||||
assign ide_da = assert_cs ? ata_addr[2:0] : 3'b111;
|
||||
|
||||
// assert r/w one cycle sort
|
||||
assign assert_rw = ata_state == s0 ||
|
||||
ata_state == s1 ||
|
||||
ata_state == s2;
|
||||
|
||||
assign ide_dior = (assert_rw && ata_rd) ? 1'b0 : 1'b1;
|
||||
assign ide_diow = (assert_rw && ata_wr) ? 1'b0 : 1'b1;
|
||||
|
||||
// send back done pulse at end
|
||||
assign ata_done = ata_state == s3;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ata_state <= idle;
|
||||
else
|
||||
ata_state <= ata_state_next;
|
||||
|
||||
always @(clk or ata_state or ata_rd or ata_wr or ata_addr or ide_data_bus)
|
||||
begin
|
||||
case (ata_state)
|
||||
idle:
|
||||
begin
|
||||
if (ata_rd || ata_wr)
|
||||
ata_state_next = s0;
|
||||
else
|
||||
ata_state_next = idle;
|
||||
end
|
||||
|
||||
s0: ata_state_next = s1;
|
||||
s1: ata_state_next = s2;
|
||||
s2: ata_state_next = s3;
|
||||
s3: ata_state_next = s4;
|
||||
s4: ata_state_next = idle;
|
||||
default: ata_state_next = idle;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ata_out <= 0;
|
||||
else
|
||||
if (ata_state == s2 && ata_rd)
|
||||
ata_out <= ide_data_bus;
|
||||
|
||||
endmodule // ide
|
||||
//
|
||||
// ide.v
|
||||
// simple state machine to do proper read & write cycles to ATA IDE device
|
||||
//
|
||||
|
||||
module ide(clk, reset, ata_rd, ata_wr, ata_addr, ata_in, ata_out, ata_done,
|
||||
ide_data_bus, ide_dior, ide_diow, ide_cs, ide_da);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
|
||||
input ata_rd;
|
||||
input ata_wr;
|
||||
input [4:0] ata_addr;
|
||||
input [15:0] ata_in;
|
||||
output [15:0] ata_out;
|
||||
reg [15:0] ata_out;
|
||||
output ata_done;
|
||||
|
||||
inout [15:0] ide_data_bus;
|
||||
output ide_dior;
|
||||
output ide_diow;
|
||||
output [1:0] ide_cs;
|
||||
output [2:0] ide_da;
|
||||
|
||||
|
||||
reg [2:0] ata_state;
|
||||
|
||||
parameter [2:0]
|
||||
idle = 3'd0,
|
||||
s0 = 3'd1,
|
||||
s1 = 3'd2,
|
||||
s2 = 3'd3,
|
||||
s3 = 3'd4,
|
||||
s4 = 3'd5;
|
||||
|
||||
wire assert_cs;
|
||||
wire assert_rw;
|
||||
|
||||
reg [2:0] ata_state_next;
|
||||
|
||||
|
||||
// if write, drive ide_bus
|
||||
assign ide_data_bus = (ata_wr && (ata_state == s0 ||
|
||||
ata_state == s1 ||
|
||||
ata_state == s2 ||
|
||||
ata_state == s3)) ? ata_in : 16'bz;
|
||||
|
||||
// assert cs & da during r/w cycle
|
||||
assign assert_cs = (ata_rd || ata_wr) && ata_state != s4;
|
||||
|
||||
assign ide_cs = assert_cs ? ata_addr[4:3] : 2'b11;
|
||||
assign ide_da = assert_cs ? ata_addr[2:0] : 3'b111;
|
||||
|
||||
// assert r/w one cycle sort
|
||||
assign assert_rw = ata_state == s0 ||
|
||||
ata_state == s1 ||
|
||||
ata_state == s2;
|
||||
|
||||
assign ide_dior = (assert_rw && ata_rd) ? 1'b0 : 1'b1;
|
||||
assign ide_diow = (assert_rw && ata_wr) ? 1'b0 : 1'b1;
|
||||
|
||||
// send back done pulse at end
|
||||
assign ata_done = ata_state == s3;
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ata_state <= idle;
|
||||
else
|
||||
ata_state <= ata_state_next;
|
||||
|
||||
always @(clk or ata_state or ata_rd or ata_wr or ata_addr or ide_data_bus)
|
||||
begin
|
||||
case (ata_state)
|
||||
idle:
|
||||
begin
|
||||
if (ata_rd || ata_wr)
|
||||
ata_state_next = s0;
|
||||
else
|
||||
ata_state_next = idle;
|
||||
end
|
||||
|
||||
s0: ata_state_next = s1;
|
||||
s1: ata_state_next = s2;
|
||||
s2: ata_state_next = s3;
|
||||
s3: ata_state_next = s4;
|
||||
s4: ata_state_next = idle;
|
||||
default: ata_state_next = idle;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ata_out <= 0;
|
||||
else
|
||||
if (ata_state == s2 && ata_rd)
|
||||
ata_out <= ide_data_bus;
|
||||
|
||||
endmodule // ide
|
||||
|
||||
850
rtl/ide_disk.v
850
rtl/ide_disk.v
@@ -1,425 +1,425 @@
|
||||
//
|
||||
// ide_disk.v
|
||||
// single block (512 byte/256 work) IDE disk read/write
|
||||
//
|
||||
|
||||
module ide_disk(clk, reset,
|
||||
ide_lba, ide_read_req, ide_write_req,
|
||||
ide_error, ide_done,
|
||||
buffer_addr, buffer_rd, buffer_wr,
|
||||
buffer_in, buffer_out,
|
||||
ide_data_bus, ide_dior, ide_diow, ide_cs, ide_da);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input [23:0] ide_lba;
|
||||
input ide_read_req;
|
||||
input ide_write_req;
|
||||
|
||||
output ide_error;
|
||||
output ide_done;
|
||||
|
||||
output reg [7:0] buffer_addr;
|
||||
output reg buffer_rd;
|
||||
output reg buffer_wr;
|
||||
output reg [11:0] buffer_out;
|
||||
input [11:0] buffer_in;
|
||||
|
||||
parameter [4:0]
|
||||
ready = 5'd0,
|
||||
init0 = 5'd1,
|
||||
init1 = 5'd2,
|
||||
init2 = 5'd3,
|
||||
init3 = 5'd4,
|
||||
init4 = 5'd5,
|
||||
init5 = 5'd6,
|
||||
init6 = 5'd7,
|
||||
init7 = 5'd8,
|
||||
init8 = 5'd9,
|
||||
init9 = 5'd10,
|
||||
init10 = 5'd11,
|
||||
init11 = 5'd12,
|
||||
read0 = 5'd13,
|
||||
read1 = 5'd14,
|
||||
write0 = 5'd15,
|
||||
write1 = 5'd16,
|
||||
last0 = 5'd17,
|
||||
last1 = 5'd18,
|
||||
last2 = 5'd19,
|
||||
last3 = 5'd20,
|
||||
wait0 = 5'd21,
|
||||
wait1 = 5'd22;
|
||||
|
||||
parameter ATA_ALTER = 5'b01110;
|
||||
parameter ATA_DEVCTRL = 5'b01110; /* bit [2] is a nIEN */
|
||||
parameter ATA_DATA = 5'b10000;
|
||||
parameter ATA_ERROR = 5'b10001;
|
||||
parameter ATA_FEATURE = 5'b10001;
|
||||
parameter ATA_SECCNT = 5'b10010;
|
||||
parameter ATA_SECNUM = 5'b10011; /* LBA[7:0] */
|
||||
parameter ATA_CYLLOW = 5'b10100; /* LBA[15:8] */
|
||||
parameter ATA_CYLHIGH = 5'b10101; /* LBA[23:16] */
|
||||
parameter ATA_DRVHEAD = 5'b10110; /* LBA + DRV + LBA[27:24] */
|
||||
parameter ATA_STATUS = 5'b10111;
|
||||
parameter ATA_COMMAND = 5'b10111;
|
||||
|
||||
parameter IDE_STATUS_BSY = 7;
|
||||
parameter IDE_STATUS_DRDY = 6;
|
||||
parameter IDE_STATUS_DWF = 5;
|
||||
parameter IDE_STATUS_DSC = 4;
|
||||
parameter IDE_STATUS_DRQ = 3;
|
||||
parameter IDE_STATUS_CORR = 2;
|
||||
parameter IDE_STATUS_IDX = 1;
|
||||
parameter IDE_STATUS_ERR = 0;
|
||||
|
||||
parameter ATA_CMD_READ = 16'h0020;
|
||||
parameter ATA_CMD_WRITE = 16'h0030;
|
||||
|
||||
reg ata_rd;
|
||||
reg ata_wr;
|
||||
reg [4:0] ata_addr;
|
||||
reg [15:0] ata_in;
|
||||
wire [15:0] ata_out;
|
||||
wire ata_done;
|
||||
|
||||
inout [15:0] ide_data_bus;
|
||||
output ide_dior;
|
||||
output ide_diow;
|
||||
output [1:0] ide_cs;
|
||||
output [2:0] ide_da;
|
||||
|
||||
//
|
||||
reg [4:0] ide_state;
|
||||
reg [4:0] ide_state_next;
|
||||
|
||||
reg [7:0] offset;
|
||||
reg [7:0] wc;
|
||||
reg err;
|
||||
reg done;
|
||||
|
||||
reg set_done, clear_done;
|
||||
reg set_err, clear_err;
|
||||
reg inc_offset;
|
||||
|
||||
//
|
||||
ide ide1(.clk(clk), .reset(reset),
|
||||
.ata_rd(ata_rd), .ata_wr(ata_wr), .ata_addr(ata_addr),
|
||||
.ata_in(ata_in), .ata_out(ata_out), .ata_done(ata_done),
|
||||
.ide_data_bus(ide_data_bus),
|
||||
.ide_dior(ide_dior), .ide_diow(ide_diow),
|
||||
.ide_cs(ide_cs), .ide_da(ide_da));
|
||||
|
||||
//
|
||||
wire [23:0] lba;
|
||||
wire start;
|
||||
|
||||
assign lba = ide_lba;
|
||||
assign start = ide_read_req | ide_write_req;
|
||||
assign ide_done = done;
|
||||
|
||||
|
||||
//
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
err <= 1'b0;
|
||||
done <= 1'b0;
|
||||
offset <= 8'b0;
|
||||
wc <= 8'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (set_err)
|
||||
err <= 1'b1;
|
||||
else
|
||||
if (clear_err)
|
||||
err <= 1'b0;
|
||||
|
||||
if (set_done)
|
||||
done <= 1'b1;
|
||||
else
|
||||
if (clear_done)
|
||||
done <= 1'b0;
|
||||
|
||||
if (inc_offset)
|
||||
begin
|
||||
offset <= offset + 8'h01;
|
||||
wc <= wc + 8'h01;
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// ide state machine
|
||||
//
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ide_state <= ready;
|
||||
else
|
||||
begin
|
||||
ide_state <= ide_state_next;
|
||||
//if (ide_state_next != ready)
|
||||
//$display("ide_state %d", ide_state_next);
|
||||
end
|
||||
|
||||
always @(ide_state or lba or start or
|
||||
ata_done or ata_out)
|
||||
begin
|
||||
ide_state_next = ide_state;
|
||||
|
||||
set_err = 0;
|
||||
clear_err = 0;
|
||||
|
||||
set_done = 0;
|
||||
clear_done = 0;
|
||||
|
||||
inc_offset = 0;
|
||||
|
||||
ata_rd = 0;
|
||||
ata_wr = 0;
|
||||
ata_addr = 0;
|
||||
ata_in = 0;
|
||||
|
||||
buffer_rd = 0;
|
||||
buffer_wr = 0;
|
||||
buffer_addr = 0;
|
||||
buffer_out = 0;
|
||||
|
||||
case (ide_state)
|
||||
ready:
|
||||
begin
|
||||
if (start)
|
||||
begin
|
||||
ide_state_next = init0;
|
||||
clear_done = 1;
|
||||
$display("ide_disk: XXX go!");
|
||||
end
|
||||
end
|
||||
|
||||
init0:
|
||||
begin
|
||||
ata_addr = ATA_STATUS;
|
||||
ata_rd = 1;
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRDY])
|
||||
ide_state_next = init1;
|
||||
end
|
||||
|
||||
init1:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DRVHEAD;
|
||||
ata_in = 16'h0040;
|
||||
if (ata_done)
|
||||
ide_state_next = wait0;
|
||||
end
|
||||
|
||||
wait0:
|
||||
begin
|
||||
// cnt = 1;
|
||||
// if (cnt_rdy)
|
||||
ide_state_next = init2;
|
||||
end
|
||||
|
||||
init2:
|
||||
begin
|
||||
ata_addr = ATA_STATUS;
|
||||
ata_rd = 1;
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRDY])
|
||||
ide_state_next = init3;
|
||||
end
|
||||
|
||||
init3:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DEVCTRL;
|
||||
ata_in = 16'h0002; // nIEN
|
||||
if (ata_done)
|
||||
ide_state_next = init4;
|
||||
end
|
||||
|
||||
init4:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_SECCNT;
|
||||
ata_in = { 8'b0, 8'd1 };
|
||||
if (ata_done)
|
||||
ide_state_next = init5;
|
||||
end
|
||||
|
||||
init5:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_SECNUM;
|
||||
ata_in = {8'b0, lba[7:0]}; // LBA[7:0]
|
||||
if (ata_done)
|
||||
ide_state_next = init6;
|
||||
end
|
||||
|
||||
init6:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_CYLLOW;
|
||||
ata_in = {8'b0, lba[15:8]}; // LBA[15:8]
|
||||
if (ata_done)
|
||||
ide_state_next = init7;
|
||||
end
|
||||
|
||||
|
||||
init7:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_CYLHIGH;
|
||||
ata_in = lba[23:16]; // LBA[23:16]
|
||||
if (ata_done)
|
||||
ide_state_next = init8;
|
||||
end
|
||||
|
||||
init8:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DRVHEAD;
|
||||
ata_in = 16'h0040; // LBA[27:24] + LBA
|
||||
if (ata_done)
|
||||
ide_state_next = init9;
|
||||
end
|
||||
|
||||
init9:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_COMMAND;
|
||||
ata_in = ide_write_req ? ATA_CMD_WRITE :
|
||||
ide_read_req ? ATA_CMD_READ : 16'b0;
|
||||
if (ata_done)
|
||||
ide_state_next = wait1;
|
||||
end
|
||||
|
||||
wait1:
|
||||
begin
|
||||
// cnt = 1;
|
||||
// if (cnt_rdy)
|
||||
ide_state_next = init10;
|
||||
end
|
||||
|
||||
init10:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_ALTER;
|
||||
if (ata_done)
|
||||
ide_state_next = init11;
|
||||
end
|
||||
|
||||
init11:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
|
||||
//if (ata_done) $display("ide_disk: XXX init11 ata_out %x", ata_out);
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRQ])
|
||||
begin
|
||||
if (ide_write_req)
|
||||
ide_state_next = write0;
|
||||
else
|
||||
if (ide_read_req)
|
||||
ide_state_next = read0;
|
||||
end
|
||||
|
||||
if (ata_out[IDE_STATUS_ERR])
|
||||
set_err = 1;
|
||||
end
|
||||
|
||||
read0:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_DATA;
|
||||
|
||||
if (ata_done)
|
||||
ide_state_next = read1;
|
||||
end
|
||||
|
||||
read1:
|
||||
begin
|
||||
//buffer write
|
||||
buffer_addr = offset;
|
||||
buffer_out = ata_out[11:0];
|
||||
|
||||
if (0) $display("ide_disk: buffer_addr %o, buffer_out %o",
|
||||
buffer_addr, buffer_out);
|
||||
|
||||
buffer_wr = 1;
|
||||
inc_offset = 1;
|
||||
|
||||
if (wc == 8'hff)
|
||||
ide_state_next = last0;
|
||||
else
|
||||
// if (wc == 16'hff00)
|
||||
// ide_state_next = init10;
|
||||
// else
|
||||
ide_state_next = read0;
|
||||
end
|
||||
|
||||
write0:
|
||||
begin
|
||||
//buffer read
|
||||
buffer_addr = offset;
|
||||
buffer_rd = 1;
|
||||
|
||||
ata_in = {4'b0, buffer_in};
|
||||
inc_offset = 1;
|
||||
ide_state_next = write1;
|
||||
end
|
||||
|
||||
write1:
|
||||
begin
|
||||
if (wc == 8'hff)
|
||||
ide_state_next = last0;
|
||||
else
|
||||
// if (wc == 16'hff00)
|
||||
// ide_state_next = init10;
|
||||
// else
|
||||
ide_state_next = write0;
|
||||
end
|
||||
|
||||
last0:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_ALTER;
|
||||
if (ata_done)
|
||||
ide_state_next = last1;
|
||||
end
|
||||
|
||||
last1:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
if (ata_done)
|
||||
ide_state_next = last2;
|
||||
end
|
||||
|
||||
last2:
|
||||
begin
|
||||
clear_err = 1;
|
||||
set_done = 1;
|
||||
ide_state_next = last3;
|
||||
end
|
||||
|
||||
last3:
|
||||
begin
|
||||
clear_done = 1;
|
||||
ide_state_next = ready;
|
||||
$display("ide_disk: XXX last3, done");
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
//
|
||||
// ide_disk.v
|
||||
// single block (512 byte/256 work) IDE disk read/write
|
||||
//
|
||||
|
||||
module ide_disk(clk, reset,
|
||||
ide_lba, ide_read_req, ide_write_req,
|
||||
ide_error, ide_done,
|
||||
buffer_addr, buffer_rd, buffer_wr,
|
||||
buffer_in, buffer_out,
|
||||
ide_data_bus, ide_dior, ide_diow, ide_cs, ide_da);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input [23:0] ide_lba;
|
||||
input ide_read_req;
|
||||
input ide_write_req;
|
||||
|
||||
output ide_error;
|
||||
output ide_done;
|
||||
|
||||
output reg [7:0] buffer_addr;
|
||||
output reg buffer_rd;
|
||||
output reg buffer_wr;
|
||||
output reg [11:0] buffer_out;
|
||||
input [11:0] buffer_in;
|
||||
|
||||
parameter [4:0]
|
||||
ready = 5'd0,
|
||||
init0 = 5'd1,
|
||||
init1 = 5'd2,
|
||||
init2 = 5'd3,
|
||||
init3 = 5'd4,
|
||||
init4 = 5'd5,
|
||||
init5 = 5'd6,
|
||||
init6 = 5'd7,
|
||||
init7 = 5'd8,
|
||||
init8 = 5'd9,
|
||||
init9 = 5'd10,
|
||||
init10 = 5'd11,
|
||||
init11 = 5'd12,
|
||||
read0 = 5'd13,
|
||||
read1 = 5'd14,
|
||||
write0 = 5'd15,
|
||||
write1 = 5'd16,
|
||||
last0 = 5'd17,
|
||||
last1 = 5'd18,
|
||||
last2 = 5'd19,
|
||||
last3 = 5'd20,
|
||||
wait0 = 5'd21,
|
||||
wait1 = 5'd22;
|
||||
|
||||
parameter ATA_ALTER = 5'b01110;
|
||||
parameter ATA_DEVCTRL = 5'b01110; /* bit [2] is a nIEN */
|
||||
parameter ATA_DATA = 5'b10000;
|
||||
parameter ATA_ERROR = 5'b10001;
|
||||
parameter ATA_FEATURE = 5'b10001;
|
||||
parameter ATA_SECCNT = 5'b10010;
|
||||
parameter ATA_SECNUM = 5'b10011; /* LBA[7:0] */
|
||||
parameter ATA_CYLLOW = 5'b10100; /* LBA[15:8] */
|
||||
parameter ATA_CYLHIGH = 5'b10101; /* LBA[23:16] */
|
||||
parameter ATA_DRVHEAD = 5'b10110; /* LBA + DRV + LBA[27:24] */
|
||||
parameter ATA_STATUS = 5'b10111;
|
||||
parameter ATA_COMMAND = 5'b10111;
|
||||
|
||||
parameter IDE_STATUS_BSY = 7;
|
||||
parameter IDE_STATUS_DRDY = 6;
|
||||
parameter IDE_STATUS_DWF = 5;
|
||||
parameter IDE_STATUS_DSC = 4;
|
||||
parameter IDE_STATUS_DRQ = 3;
|
||||
parameter IDE_STATUS_CORR = 2;
|
||||
parameter IDE_STATUS_IDX = 1;
|
||||
parameter IDE_STATUS_ERR = 0;
|
||||
|
||||
parameter ATA_CMD_READ = 16'h0020;
|
||||
parameter ATA_CMD_WRITE = 16'h0030;
|
||||
|
||||
reg ata_rd;
|
||||
reg ata_wr;
|
||||
reg [4:0] ata_addr;
|
||||
reg [15:0] ata_in;
|
||||
wire [15:0] ata_out;
|
||||
wire ata_done;
|
||||
|
||||
inout [15:0] ide_data_bus;
|
||||
output ide_dior;
|
||||
output ide_diow;
|
||||
output [1:0] ide_cs;
|
||||
output [2:0] ide_da;
|
||||
|
||||
//
|
||||
reg [4:0] ide_state;
|
||||
reg [4:0] ide_state_next;
|
||||
|
||||
reg [7:0] offset;
|
||||
reg [7:0] wc;
|
||||
reg err;
|
||||
reg done;
|
||||
|
||||
reg set_done, clear_done;
|
||||
reg set_err, clear_err;
|
||||
reg inc_offset;
|
||||
|
||||
//
|
||||
ide ide1(.clk(clk), .reset(reset),
|
||||
.ata_rd(ata_rd), .ata_wr(ata_wr), .ata_addr(ata_addr),
|
||||
.ata_in(ata_in), .ata_out(ata_out), .ata_done(ata_done),
|
||||
.ide_data_bus(ide_data_bus),
|
||||
.ide_dior(ide_dior), .ide_diow(ide_diow),
|
||||
.ide_cs(ide_cs), .ide_da(ide_da));
|
||||
|
||||
//
|
||||
wire [23:0] lba;
|
||||
wire start;
|
||||
|
||||
assign lba = ide_lba;
|
||||
assign start = ide_read_req | ide_write_req;
|
||||
assign ide_done = done;
|
||||
|
||||
|
||||
//
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
begin
|
||||
err <= 1'b0;
|
||||
done <= 1'b0;
|
||||
offset <= 8'b0;
|
||||
wc <= 8'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (set_err)
|
||||
err <= 1'b1;
|
||||
else
|
||||
if (clear_err)
|
||||
err <= 1'b0;
|
||||
|
||||
if (set_done)
|
||||
done <= 1'b1;
|
||||
else
|
||||
if (clear_done)
|
||||
done <= 1'b0;
|
||||
|
||||
if (inc_offset)
|
||||
begin
|
||||
offset <= offset + 8'h01;
|
||||
wc <= wc + 8'h01;
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// ide state machine
|
||||
//
|
||||
always @(posedge clk)
|
||||
if (reset)
|
||||
ide_state <= ready;
|
||||
else
|
||||
begin
|
||||
ide_state <= ide_state_next;
|
||||
//if (ide_state_next != ready)
|
||||
//$display("ide_state %d", ide_state_next);
|
||||
end
|
||||
|
||||
always @(ide_state or lba or start or
|
||||
ata_done or ata_out)
|
||||
begin
|
||||
ide_state_next = ide_state;
|
||||
|
||||
set_err = 0;
|
||||
clear_err = 0;
|
||||
|
||||
set_done = 0;
|
||||
clear_done = 0;
|
||||
|
||||
inc_offset = 0;
|
||||
|
||||
ata_rd = 0;
|
||||
ata_wr = 0;
|
||||
ata_addr = 0;
|
||||
ata_in = 0;
|
||||
|
||||
buffer_rd = 0;
|
||||
buffer_wr = 0;
|
||||
buffer_addr = 0;
|
||||
buffer_out = 0;
|
||||
|
||||
case (ide_state)
|
||||
ready:
|
||||
begin
|
||||
if (start)
|
||||
begin
|
||||
ide_state_next = init0;
|
||||
clear_done = 1;
|
||||
$display("ide_disk: XXX go!");
|
||||
end
|
||||
end
|
||||
|
||||
init0:
|
||||
begin
|
||||
ata_addr = ATA_STATUS;
|
||||
ata_rd = 1;
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRDY])
|
||||
ide_state_next = init1;
|
||||
end
|
||||
|
||||
init1:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DRVHEAD;
|
||||
ata_in = 16'h0040;
|
||||
if (ata_done)
|
||||
ide_state_next = wait0;
|
||||
end
|
||||
|
||||
wait0:
|
||||
begin
|
||||
// cnt = 1;
|
||||
// if (cnt_rdy)
|
||||
ide_state_next = init2;
|
||||
end
|
||||
|
||||
init2:
|
||||
begin
|
||||
ata_addr = ATA_STATUS;
|
||||
ata_rd = 1;
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRDY])
|
||||
ide_state_next = init3;
|
||||
end
|
||||
|
||||
init3:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DEVCTRL;
|
||||
ata_in = 16'h0002; // nIEN
|
||||
if (ata_done)
|
||||
ide_state_next = init4;
|
||||
end
|
||||
|
||||
init4:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_SECCNT;
|
||||
ata_in = { 8'b0, 8'd1 };
|
||||
if (ata_done)
|
||||
ide_state_next = init5;
|
||||
end
|
||||
|
||||
init5:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_SECNUM;
|
||||
ata_in = {8'b0, lba[7:0]}; // LBA[7:0]
|
||||
if (ata_done)
|
||||
ide_state_next = init6;
|
||||
end
|
||||
|
||||
init6:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_CYLLOW;
|
||||
ata_in = {8'b0, lba[15:8]}; // LBA[15:8]
|
||||
if (ata_done)
|
||||
ide_state_next = init7;
|
||||
end
|
||||
|
||||
|
||||
init7:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_CYLHIGH;
|
||||
ata_in = lba[23:16]; // LBA[23:16]
|
||||
if (ata_done)
|
||||
ide_state_next = init8;
|
||||
end
|
||||
|
||||
init8:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_DRVHEAD;
|
||||
ata_in = 16'h0040; // LBA[27:24] + LBA
|
||||
if (ata_done)
|
||||
ide_state_next = init9;
|
||||
end
|
||||
|
||||
init9:
|
||||
begin
|
||||
ata_wr = 1;
|
||||
ata_addr = ATA_COMMAND;
|
||||
ata_in = ide_write_req ? ATA_CMD_WRITE :
|
||||
ide_read_req ? ATA_CMD_READ : 16'b0;
|
||||
if (ata_done)
|
||||
ide_state_next = wait1;
|
||||
end
|
||||
|
||||
wait1:
|
||||
begin
|
||||
// cnt = 1;
|
||||
// if (cnt_rdy)
|
||||
ide_state_next = init10;
|
||||
end
|
||||
|
||||
init10:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_ALTER;
|
||||
if (ata_done)
|
||||
ide_state_next = init11;
|
||||
end
|
||||
|
||||
init11:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
|
||||
//if (ata_done) $display("ide_disk: XXX init11 ata_out %x", ata_out);
|
||||
if (ata_done &&
|
||||
~ata_out[IDE_STATUS_BSY] &&
|
||||
ata_out[IDE_STATUS_DRQ])
|
||||
begin
|
||||
if (ide_write_req)
|
||||
ide_state_next = write0;
|
||||
else
|
||||
if (ide_read_req)
|
||||
ide_state_next = read0;
|
||||
end
|
||||
|
||||
if (ata_out[IDE_STATUS_ERR])
|
||||
set_err = 1;
|
||||
end
|
||||
|
||||
read0:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_DATA;
|
||||
|
||||
if (ata_done)
|
||||
ide_state_next = read1;
|
||||
end
|
||||
|
||||
read1:
|
||||
begin
|
||||
//buffer write
|
||||
buffer_addr = offset;
|
||||
buffer_out = ata_out[11:0];
|
||||
|
||||
if (0) $display("ide_disk: buffer_addr %o, buffer_out %o",
|
||||
buffer_addr, buffer_out);
|
||||
|
||||
buffer_wr = 1;
|
||||
inc_offset = 1;
|
||||
|
||||
if (wc == 8'hff)
|
||||
ide_state_next = last0;
|
||||
else
|
||||
// if (wc == 16'hff00)
|
||||
// ide_state_next = init10;
|
||||
// else
|
||||
ide_state_next = read0;
|
||||
end
|
||||
|
||||
write0:
|
||||
begin
|
||||
//buffer read
|
||||
buffer_addr = offset;
|
||||
buffer_rd = 1;
|
||||
|
||||
ata_in = {4'b0, buffer_in};
|
||||
inc_offset = 1;
|
||||
ide_state_next = write1;
|
||||
end
|
||||
|
||||
write1:
|
||||
begin
|
||||
if (wc == 8'hff)
|
||||
ide_state_next = last0;
|
||||
else
|
||||
// if (wc == 16'hff00)
|
||||
// ide_state_next = init10;
|
||||
// else
|
||||
ide_state_next = write0;
|
||||
end
|
||||
|
||||
last0:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_ALTER;
|
||||
if (ata_done)
|
||||
ide_state_next = last1;
|
||||
end
|
||||
|
||||
last1:
|
||||
begin
|
||||
ata_rd = 1;
|
||||
ata_addr = ATA_STATUS;
|
||||
if (ata_done)
|
||||
ide_state_next = last2;
|
||||
end
|
||||
|
||||
last2:
|
||||
begin
|
||||
clear_err = 1;
|
||||
set_done = 1;
|
||||
ide_state_next = last3;
|
||||
end
|
||||
|
||||
last3:
|
||||
begin
|
||||
clear_done = 1;
|
||||
ide_state_next = ready;
|
||||
$display("ide_disk: XXX last3, done");
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
/* 256x12 static ram */
|
||||
module ram_256x12(A, DI, DO, CE_N, WE_N);
|
||||
|
||||
input [7:0] A;
|
||||
input [11:0] DI;
|
||||
input CE_N, WE_N;
|
||||
output [11:0] DO;
|
||||
|
||||
reg [11:0] ram [0:255];
|
||||
integer i;
|
||||
|
||||
initial
|
||||
begin
|
||||
for (i = 0; i < 256; i=i+1)
|
||||
ram[i] = 12'b0;
|
||||
end
|
||||
|
||||
always @(WE_N or CE_N or A or DI)
|
||||
begin
|
||||
if (WE_N == 0 && CE_N == 0)
|
||||
begin
|
||||
`ifdef debug_ram
|
||||
$display("rf: buffer ram write [%o] <- %o", A, DI);
|
||||
`endif
|
||||
ram[ A ] = DI;
|
||||
end
|
||||
|
||||
`ifdef debug_ram
|
||||
if (WE_N == 1 && CE_N == 0)
|
||||
$display("rf: buffer ram read [%o] -> %o", A, ram[A]);
|
||||
`endif
|
||||
end
|
||||
|
||||
assign DO = ram[ A ];
|
||||
|
||||
endmodule
|
||||
|
||||
/* 256x12 static ram */
|
||||
module ram_256x12(A, DI, DO, CE_N, WE_N);
|
||||
|
||||
input [7:0] A;
|
||||
input [11:0] DI;
|
||||
input CE_N, WE_N;
|
||||
output [11:0] DO;
|
||||
|
||||
reg [11:0] ram [0:255];
|
||||
integer i;
|
||||
|
||||
initial
|
||||
begin
|
||||
for (i = 0; i < 256; i=i+1)
|
||||
ram[i] = 12'b0;
|
||||
end
|
||||
|
||||
always @(WE_N or CE_N or A or DI)
|
||||
begin
|
||||
if (WE_N == 0 && CE_N == 0)
|
||||
begin
|
||||
`ifdef debug_ram
|
||||
$display("rf: buffer ram write [%o] <- %o", A, DI);
|
||||
`endif
|
||||
ram[ A ] = DI;
|
||||
end
|
||||
|
||||
`ifdef debug_ram
|
||||
if (WE_N == 1 && CE_N == 0)
|
||||
$display("rf: buffer ram read [%o] -> %o", A, ram[A]);
|
||||
`endif
|
||||
end
|
||||
|
||||
assign DO = ram[ A ];
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
Reference in New Issue
Block a user