-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathide_fifo.v
86 lines (74 loc) · 2.66 KB
/
ide_fifo.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
module ide_fifo
(
input clk, // bus clock
input clk_en,
input reset, // reset
input [15:0] data_in, // data in
output reg [15:0] data_out, // data out
input rd, // read from fifo
input wr, // write to fifo
input packet_in,
input packet_out,
input [12:0] packet_count,
output packet_in_last, // last word is read in packet_in state
output full, // fifo is full
output empty, // fifo is empty
output last_out, // the last word of a sector is being read
output last_in // the last word of a sector is being written
);
// local signals and registers
reg [15:0] mem [4095:0]; // 16 bit wide fifo memory
reg [12:0] inptr; // fifo input pointer
reg [12:0] outptr; // fifo output pointer
wire empty_rd; // fifo empty flag (set immediately after reading the last word)
reg empty_wr; // fifo empty flag (set one clock after writting the empty fifo)
reg rd_old;
reg wr_old;
always @(posedge clk)
if (clk_en) begin
rd_old <= rd;
wr_old <= wr;
end
// main fifo memory (implemented using synchronous block ram)
always @(posedge clk)
if (clk_en) begin
if (wr)
mem[inptr[11:0]] <= data_in;
end
always @(posedge clk)
if (clk_en)
data_out <= mem[outptr[11:0]];
// fifo write pointer control
always @(posedge clk)
if (clk_en) begin
if (reset)
inptr <= 0;
else if (wr_old & ~wr)
inptr <= inptr + 1'd1;
end
// fifo read pointer control
always @(posedge clk)
if (clk_en) begin
if (reset)
outptr <= 0;
else if (rd_old & ~rd)
outptr <= outptr + 1'd1;
end
// the empty flag is set immediately after reading the last word from the fifo
assign empty_rd = inptr==outptr ? 1'b1 : 1'b0;
// after writting empty fifo the empty flag is delayed by one clock to handle ram write delay
always @(posedge clk)
if (clk_en)
empty_wr <= empty_rd;
assign empty = empty_rd | empty_wr;
// at least 512 bytes are in FIFO
// this signal is activated when 512th byte is written to the empty fifo
// then it's deactivated when 512th byte is read from the fifo (hysteresis)
// special handlig of packet commands
assign full = (inptr[12:8] != outptr[12:8] && !packet_in && !packet_out) ||
(packet_in && inptr == packet_count && inptr != outptr) ||
(packet_out && inptr == packet_count /*&& inptr != outptr*/);
assign packet_in_last = packet_in && inptr == packet_count && inptr == outptr && inptr != 0;
assign last_out = outptr[7:0] == 8'hFF ? 1'b1 : 1'b0;
assign last_in = inptr [7:0] == 8'hFF ? 1'b1 : 1'b0;
endmodule