100 lines
2.1 KiB
Verilog
100 lines
2.1 KiB
Verilog
//
|
|
// 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
|