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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [floppy/] [floppy.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
module floppy(
28
    input               clk,
29
    input               rst_n,
30
 
31
    //dma
32
    output              dma_floppy_req,
33
    input               dma_floppy_ack,
34
    input               dma_floppy_terminal,
35
    input       [7:0]   dma_floppy_readdata,
36
    output      [7:0]   dma_floppy_writedata,
37
 
38
    //irq
39
    output reg          irq,
40
 
41
    //avalon slave
42
    input       [2:0]   io_address,
43
    input               io_read,
44
    output reg  [7:0]   io_readdata,
45
    input               io_write,
46
    input       [7:0]   io_writedata,
47
 
48
    //ide shared port 0x3F6
49
    output              ide_3f6_read,
50
    input       [7:0]   ide_3f6_readdata,
51
    output              ide_3f6_write,
52
    output      [7:0]   ide_3f6_writedata,
53
 
54
    //master to control sd
55
    output      [31:0]  sd_master_address,
56
    input               sd_master_waitrequest,
57
    output              sd_master_read,
58
    input               sd_master_readdatavalid,
59
    input       [31:0]  sd_master_readdata,
60
    output              sd_master_write,
61
    output      [31:0]  sd_master_writedata,
62
 
63
    //slave for sd
64
    input       [8:0]   sd_slave_address,
65
    input               sd_slave_read,
66
    output reg  [7:0]   sd_slave_readdata,
67
    input               sd_slave_write,
68
    input       [7:0]   sd_slave_writedata,
69
 
70
    //slave for management
71
    /*
72
     0x00.[0]:      media present
73
     0x01.[0]:      media writeprotect
74
     0x02.[7:0]:    media cylinders
75
     0x03.[7:0]:    media sectors per track
76
     0x04.[31:0]:   media total sector count
77
     0x05.[1:0]:    media heads
78
     0x06.[31:0]:   media sd base
79
     0x07.[15:0]:   media wait cycles: 200000 us / spt
80
     0x08.[15:0]:   media wait rate 0: 1000 us
81
     0x09.[15:0]:   media wait rate 1: 1666 us
82
     0x0A.[15:0]:   media wait rate 2: 2000 us
83
     0x0B.[15:0]:   media wait rate 3: 500 us
84
     0x0C.[7:0]:    media type: 8'h20 none; 8'h00 old; 8'hC0 720k; 8'h80 1_44M; 8'h40 2_88M
85
    */
86
    input       [3:0]   mgmt_address,
87
    input               mgmt_write,
88
    input       [31:0]  mgmt_writedata
89
);
90
 
91
//------------------------------------------------------------------------------
92
 
93
`define SD_AVALON_BASE_ADDRESS_FOR_FDD 32'h00000800
94
 
95
//TODO: in execute_ndma -- send irq after every byte
96
 
97
//------------------------------------------------------------------------------
98
 
99
reg io_read_last;
100
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) io_read_last <= 1'b0; else if(io_read_last) io_read_last <= 1'b0; else io_read_last <= io_read; end
101
wire io_read_valid = io_read && io_read_last == 1'b0;
102
 
103
reg sd_slave_read_last;
104
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sd_slave_read_last <= 1'b0; else if(sd_slave_read_last) sd_slave_read_last <= 1'b0; else sd_slave_read_last <= sd_slave_read; end
105
wire sd_slave_read_valid = sd_slave_read && sd_slave_read_last == 1'b0;
106
 
107
//------------------------------------------------------------------------------ ide shared ports
108
 
109
assign ide_3f6_read      = io_read_valid && io_address == 3'd6;
110
assign ide_3f6_write     = io_write && io_address == 3'd6;
111
assign ide_3f6_writedata = io_writedata;
112
 
113
//------------------------------------------------------------------------------ io read
114
 
115
wire read_in_io_mode  = io_read_valid && io_address == 3'd5 && execute_ndma && cmd_read_normal_in_progress;
116
 
117
wire write_in_io_mode = io_write && io_address == 3'h5 && execute_ndma && (cmd_write_normal_in_progress || cmd_format_in_progress);
118
 
119
wire [7:0] io_readdata_prepare =
120
    (io_address == 3'd2)?   { 3'b0, motor_enable, dma_irq_enable, enable, selected_drive } :        //digital output register
121
    (io_address == 3'd3)?   media_type :                                                            //tape drive register
122
    (io_address == 3'd4)?   { datareg_ready, transfer_to_cpu, execute_ndma, busy, in_seek_mode } :  //main status reg
123
    (read_in_io_mode)?      from_floppy_q :
124
    (io_address == 3'd5)?   reply[7:0] :
125
    (io_address == 3'd6)?   ide_3f6_readdata :
126
    (io_address == 3'd7)?   { change, 7'h7F } :
127
                            8'd0;
128
 
129
always @(posedge clk or negedge rst_n) begin
130
    if(rst_n == 1'b0)   io_readdata <= 8'd0;
131
    else                io_readdata <= io_readdata_prepare;
132
end
133
 
134
//------------------------------------------------------------------------------ media management
135
 
136
reg media_present;
137
always @(posedge clk or negedge rst_n) begin
138
    if(rst_n == 1'b0)                           media_present <= 1'b0;
139
    else if(mgmt_write && mgmt_address == 4'd0) media_present <= mgmt_writedata[0];
140
end
141
 
142
reg media_writeprotected;
143
always @(posedge clk or negedge rst_n) begin
144
    if(rst_n == 1'b0)                           media_writeprotected <= 1'b0;
145
    else if(mgmt_write && mgmt_address == 4'd1) media_writeprotected <= mgmt_writedata[0];
146
end
147
 
148
reg [7:0] media_cylinders;
149
always @(posedge clk or negedge rst_n) begin
150
    if(rst_n == 1'b0)                           media_cylinders <= 8'd0;
151
    else if(mgmt_write && mgmt_address == 4'd2) media_cylinders <= mgmt_writedata[7:0];
152
end
153
 
154
reg [7:0] media_sectors_per_track;
155
always @(posedge clk or negedge rst_n) begin
156
    if(rst_n == 1'b0)                           media_sectors_per_track <= 8'd0;
157
    else if(mgmt_write && mgmt_address == 4'd3) media_sectors_per_track <= mgmt_writedata[7:0];
158
end
159
 
160
reg [31:0] media_sector_count;
161
always @(posedge clk or negedge rst_n) begin
162
    if(rst_n == 1'b0)                           media_sector_count <= 32'd0;
163
    else if(mgmt_write && mgmt_address == 4'd4) media_sector_count <= mgmt_writedata;
164
end
165
 
166
reg [1:0] media_heads;
167
always @(posedge clk or negedge rst_n) begin
168
    if(rst_n == 1'b0)                           media_heads <= 2'd2;
169
    else if(mgmt_write && mgmt_address == 4'd5) media_heads <= mgmt_writedata[1:0];
170
end
171
 
172
reg [31:0] media_sd_base;
173
always @(posedge clk or negedge rst_n) begin
174
    if(rst_n == 1'b0)                           media_sd_base <= 32'd0;
175
    else if(mgmt_write && mgmt_address == 4'd6) media_sd_base <= mgmt_writedata;
176
end
177
 
178
reg [15:0] media_wait_cycles;
179
always @(posedge clk or negedge rst_n) begin
180
    if(rst_n == 1'b0)                           media_wait_cycles <= 16'd0;
181
    else if(mgmt_write && mgmt_address == 4'd7) media_wait_cycles <= mgmt_writedata[15:0];
182
end
183
 
184
reg [15:0] media_wait_rate_0;
185
reg [15:0] media_wait_rate_1;
186
reg [15:0] media_wait_rate_2;
187
reg [15:0] media_wait_rate_3;
188
 
189
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) media_wait_rate_0 <= 16'd1000; else if(mgmt_write && mgmt_address == 4'h8) media_wait_rate_0 <= mgmt_writedata[15:0]; end
190
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) media_wait_rate_1 <= 16'd1666; else if(mgmt_write && mgmt_address == 4'h9) media_wait_rate_1 <= mgmt_writedata[15:0]; end
191
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) media_wait_rate_2 <= 16'd2000; else if(mgmt_write && mgmt_address == 4'hA) media_wait_rate_2 <= mgmt_writedata[15:0]; end
192
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) media_wait_rate_3 <= 16'd500;  else if(mgmt_write && mgmt_address == 4'hB) media_wait_rate_3 <= mgmt_writedata[15:0]; end
193
 
194
reg [7:0] media_type;
195
always @(posedge clk or negedge rst_n) begin
196
    if(rst_n == 1'b0)                           media_type <= 8'h20;
197
    else if(mgmt_write && mgmt_address == 4'hC) media_type <= mgmt_writedata[7:0];
198
end
199
 
200
//------------------------------------------------------------------------------
201
 
202
wire sw_reset =
203
    (io_write && io_address == 3'h2 && io_writedata[2] == 1'b0 && enable) ||
204
    (io_write && io_address == 3'h4 && io_writedata[7]);
205
 
206
reg [1:0] selected_drive;
207
always @(posedge clk or negedge rst_n) begin
208
    if(rst_n == 1'b0)                           selected_drive <= 2'd0;
209
    else if(io_write && io_address == 3'h2)     selected_drive <= io_writedata[1:0];
210
    else if(cmd_recalibrate_start)              selected_drive <= io_writedata[1:0];
211
    else if(cmd_seek_start)                     selected_drive <= command[1:0];
212
    else if(cmd_read_id_start)                  selected_drive <= io_writedata[1:0];
213
    else if(cmd_format_track_start)             selected_drive <= command[25:24];
214
    else if(cmd_read_write_start)               selected_drive <= command[49:48];
215
end
216
 
217
reg motor_enable;
218
always @(posedge clk or negedge rst_n) begin
219
    if(rst_n == 1'b0)                           motor_enable <= 1'b0;
220
    else if(io_write && io_address == 3'h2)     motor_enable <= io_writedata[4];
221
end
222
 
223
reg dma_irq_enable;
224
always @(posedge clk or negedge rst_n) begin
225
    if(rst_n == 1'b0)                           dma_irq_enable <= 1'b1;
226
    else if(io_write && io_address == 3'h2)     dma_irq_enable <= io_writedata[3];
227
end
228
 
229
reg enable;
230
always @(posedge clk or negedge rst_n) begin
231
    if(rst_n == 1'b0)                           enable <= 1'b1;
232
    else if(io_write && io_address == 3'h2)     enable <= io_writedata[2];
233
end
234
 
235
reg [1:0] data_rate;
236
always @(posedge clk or negedge rst_n) begin
237
    if(rst_n == 1'b0)                           data_rate <= 2'b10;
238
    else if(io_write && io_address == 3'h4)     data_rate <= io_writedata[1:0];
239
    else if(io_write && io_address == 3'h7)     data_rate <= io_writedata[1:0];
240
end
241
 
242
reg datareg_ready;
243
always @(posedge clk or negedge rst_n) begin
244
    if(rst_n == 1'b0)                               datareg_ready <= 1'b1;
245
    else if(sw_reset)                               datareg_ready <= 1'b1;
246
 
247
    else if(cmd_read_write_ok_at_start)             datareg_ready <= 1'b0;
248
    else if(cmd_read_id_ok_at_start)                datareg_ready <= 1'b0;
249
    else if(cmd_format_ok_at_start)                 datareg_ready <= 1'b0;
250
 
251
    else if(execute_ndma && state == S_WAIT_FOR_EMPTY_READ_FIFO && read_in_io_mode)                                 datareg_ready <= 1'b0;
252
    else if(execute_ndma && state == S_WAIT_FOR_EMPTY_READ_FIFO && ~(from_floppy_empty))                            datareg_ready <= 1'b1;
253
 
254
    else if(execute_ndma && state == S_WAIT_FOR_FULL_WRITE_FIFO && to_floppy_count == 11'd511 && write_in_io_mode)  datareg_ready <= 1'b0;
255
    else if(execute_ndma && state == S_WAIT_FOR_FULL_WRITE_FIFO && to_floppy_count < 11'd512)                       datareg_ready <= 1'b1;
256
 
257
    else if(execute_ndma && state == S_WAIT_FOR_FORMAT_INPUT && format_data_count == 3'd3 && write_in_io_mode)      datareg_ready <= 1'b0;
258
    else if(execute_ndma && state == S_WAIT_FOR_FORMAT_INPUT && format_data_count < 3'd4)                           datareg_ready <= 1'b1;
259
 
260
    else if(enter_result_phase)                                                                                     datareg_ready <= 1'b1;
261
end
262
 
263
reg execute_ndma;
264
always @(posedge clk or negedge rst_n) begin
265
    if(rst_n == 1'b0)                               execute_ndma <= 1'b0;
266
    else if(cmd_read_write_ok_at_start && ndma)     execute_ndma <= 1'b1;
267
    else if(cmd_format_ok_at_start && ndma)         execute_ndma <= 1'b1;
268
    else if(enter_result_phase)                     execute_ndma <= 1'b0;
269
end
270
 
271
reg transfer_to_cpu;
272
always @(posedge clk or negedge rst_n) begin
273
    if(rst_n == 1'b0)                                                   transfer_to_cpu <= 1'b0;
274
    else if(sw_reset)                                                   transfer_to_cpu <= 1'b0;
275
    else if(command_first && ~(enter_result_phase))                     transfer_to_cpu <= 1'b0;
276
    else if(execute_ndma && state == S_WAIT_FOR_EMPTY_READ_FIFO)        transfer_to_cpu <= 1'b1;
277
    else if(enter_result_phase)                                         transfer_to_cpu <= 1'b1;
278
    else if(io_read_valid && io_address == 3'd5 && reply_left == 4'd1)  transfer_to_cpu <= 1'b0;
279
end
280
 
281
reg busy;
282
always @(posedge clk or negedge rst_n) begin
283
    if(rst_n == 1'b0)                                                   busy <= 1'b0;
284
    else if(sw_reset)                                                   busy <= 1'b0;
285
    else if(command_first)                                              busy <= 1'b1;
286
    else if(cmd_recalibrate_start)                                      busy <= 1'b0;
287
    else if(cmd_seek_start)                                             busy <= 1'b0;
288
    else if(cmd_specify_start)                                          busy <= 1'b0;
289
    else if(cmd_configure_mode_start)                                   busy <= 1'b0;
290
    else if(cmd_perpendicular_mode_start)                               busy <= 1'b0;
291
    else if(enter_result_phase)                                         busy <= 1'b1;
292
    else if(io_read_valid && io_address == 3'd5 && reply_left == 4'd1)  busy <= 1'b0;
293
end
294
 
295
reg change;
296
always @(posedge clk or negedge rst_n) begin
297
    if(rst_n == 1'b0)                                                       change <= 1'b1;
298
    else if(~(media_present))                                               change <= 1'b1;
299
    else if(reset_changeline && selected_drive == 2'd0 && media_present)    change <= 1'b0;
300
end
301
 
302
reg [3:0] in_seek_mode;
303
always @(posedge clk or negedge rst_n) begin
304
    if(rst_n == 1'b0)                   in_seek_mode <= 4'd0;
305
    else if(sw_reset)                   in_seek_mode <= 4'd0;
306
    else if(cmd_recalibrate_start)      in_seek_mode <= (io_writedata[1:0] == 2'd0)? 4'b0001 : (io_writedata[1:0] == 2'd1)? 4'b0010 : (io_writedata[1:0] == 2'd2)? 4'b0100 : 4'b1000;
307
    else if(cmd_seek_start)             in_seek_mode <= (command[1:0] == 2'd0)? 4'b0001 : (command[1:0] == 2'd1)? 4'b0010 : (command[1:0] == 2'd2)? 4'b0100 : 4'b1000;
308
end
309
 
310
//------------------------------------------------------------------------------
311
 
312
wire command_first = io_write && io_address == 3'h5 && state == S_IDLE && command_left == 4'd0 && ~(busy);
313
wire command_next  = io_write && io_address == 3'h5 && state == S_IDLE && command_left > 4'd0;
314
 
315
reg [71:0] command;
316
always @(posedge clk or negedge rst_n) begin
317
    if(rst_n == 1'b0)           command <= 72'd0;
318
    else if(command_first)      command <= { command[63:0], io_writedata };
319
    else if(command_next)       command <= { command[63:0], io_writedata };
320
end
321
 
322
wire [3:0] command_at_first =
323
    (io_writedata == 8'h03)?                    4'd2 :                      //specify command
324
    (io_writedata == 8'h04)?                    4'd1 :                      //get status
325
    (io_writedata == 8'h07)?                    4'd1 :                      //recalibrate
326
    (io_writedata == 8'h0F)?                    4'd2 :                      //seek
327
    (io_writedata == 8'h4A)?                    4'd1 :                      //read ID
328
    (io_writedata == 8'h4D)?                    4'd5 :                      //format track
329
    ({ 1'b0, io_writedata[6:0] } == 8'h45)?     4'd8 :                      //write normal data
330
    ({ 1'b0, io_writedata[6], 1'b0, io_writedata[4:0] } ==  8'h46)?  4'd8 : //read normal data
331
    (io_writedata == 8'h12)?                    4'd1 :                      //perpendicular mode (Enhanced)
332
    (io_writedata == 8'h13)?                    4'd3 :                      //configure command (Enhanced)
333
                                                4'd0;
334
 
335
reg [3:0] command_size;
336
always @(posedge clk or negedge rst_n) begin
337
    if(rst_n == 1'b0)                                   command_size <= 4'd0;
338
 
339
    else if(command_first && command_at_first != 4'd0)  command_size <= command_at_first;
340
end
341
 
342
reg [3:0] command_left;
343
always @(posedge clk or negedge rst_n) begin
344
    if(rst_n == 1'b0)                                       command_left <= 4'd0;
345
 
346
    else if(command_first && command_at_first != 4'd0)      command_left <= command_at_first;
347
    else if(command_next)                                   command_left <= command_left - 4'd1;
348
end
349
 
350
reg [7:0] pending_command;
351
always @(posedge clk or negedge rst_n) begin
352
    if(rst_n == 1'b0)                           pending_command <= 8'b0;
353
    else if(sw_reset)                           pending_command <= 8'h00;
354
    else if(cmd_read_write_ok_at_start)         pending_command <= command[63:56];
355
    else if(cmd_read_id_ok_at_start)            pending_command <= 8'h4A;
356
    else if(cmd_format_ok_at_start)             pending_command <= command[39:32];
357
    else if(cmd_recalibrate_start)              pending_command <= 8'h07;
358
    else if(enter_result_phase)                 pending_command <= 8'h00;
359
end
360
 
361
wire cmd_sense_interrupt_status_start   = command_first && io_writedata == 8'h08;       //enters result phase
362
wire cmd_dump_registers_start           = command_first && io_writedata == 8'h0E;       //enters result phase
363
wire cmd_version_start                  = command_first && io_writedata == 8'h10;       //enters result phase
364
wire cmd_unlock_start                   = command_first && io_writedata == 8'h14;       //enters result phase
365
wire cmd_lock_start                     = command_first && io_writedata == 8'h94;       //enters result phase
366
 
367
wire cmd_specify_start        = command_size == 4'd2 && command_next && command_left == 4'd1 && command[15:8]  == 8'h03;    //immediate finish
368
wire cmd_get_status_start     = command_size == 4'd1 && command_next && command_left == 4'd1 && command[7:0]   == 8'h04;    //enters result phase
369
wire cmd_recalibrate_start    = command_size == 4'd1 && command_next && command_left == 4'd1 && command[7:0]   == 8'h07;    //interrupt after delay
370
wire cmd_seek_start           = command_size == 4'd2 && command_next && command_left == 4'd1 && command[15:8]  == 8'h0F;    //interrupt after delay
371
wire cmd_read_id_start        = command_size == 4'd1 && command_next && command_left == 4'd1 && command[7:0]   == 8'h4A;    //enters result phase
372
wire cmd_format_track_start   = command_size == 4'd5 && command_next && command_left == 4'd1 && command[39:32] == 8'h4D;    //enters result pahse
373
wire cmd_write_normal_start   = command_size == 4'd8 && command_next && command_left == 4'd1 && { 1'b0, command[62:56] } == 8'h45;                      //enters result phase
374
wire cmd_read_normal_start    = command_size == 4'd8 && command_next && command_left == 4'd1 && { 1'b0, command[62], 1'b0, command[60:56] } ==  8'h46;  //enters result phase
375
 
376
wire cmd_perpendicular_mode_start = command_size == 4'd1 && command_next && command_left == 4'd1 && command[7:0]   == 8'h12;    //immediate finish
377
wire cmd_configure_mode_start     = command_size == 4'd3 && command_next && command_left == 4'd1 && command[23:16] == 8'h13;    //immediate finish
378
 
379
wire cmd_invalid_start = command_first &&
380
    io_writedata != 8'h03 &&
381
    io_writedata != 8'h04 &&
382
    io_writedata != 8'h07 &&
383
    io_writedata != 8'h08 &&
384
    io_writedata != 8'h0F &&
385
    io_writedata != 8'h4A &&
386
    io_writedata != 8'h4D &&
387
    { 1'b0, io_writedata[6:0] } != 8'h45 &&
388
    { 1'b0, io_writedata[6], 1'b0, io_writedata[4:0] } !=  8'h46 &&
389
    io_writedata != 8'h0E &&
390
    io_writedata != 8'h10 &&
391
    io_writedata != 8'h14 &&
392
    io_writedata != 8'h94 &&
393
    io_writedata != 8'h12 &&
394
    io_writedata != 8'h13;
395
 
396
wire cmd_read_write_start = cmd_read_normal_start || cmd_write_normal_start;
397
 
398
wire cmd_read_normal_in_progress  = { 1'b0, pending_command[6], 1'b0, pending_command[4:0] } ==  8'h46;
399
wire cmd_write_normal_in_progress = { 1'b0, pending_command[6:0] } == 8'h45;
400
wire cmd_format_in_progress       = pending_command == 8'h4D;
401
wire cmd_recalibrate_in_progress  = pending_command == 8'h07;
402
wire cmd_read_id_in_progress      = pending_command == 8'h4A;
403
 
404
wire enter_result_phase =
405
    cmd_invalid_start || cmd_sense_interrupt_status_start || cmd_dump_registers_start || cmd_version_start || cmd_unlock_start || cmd_lock_start ||
406
    (cmd_read_write_start && (cmd_read_write_incorrect_head_at_start || cmd_read_write_incorrect_sector_at_start || cmd_write_and_writeprotected_at_start)) ||
407
    (state == S_CHECK_TC && (cmd_read_write_finish || cmd_format_finish)) ||
408
    (cmd_format_track_start && cmd_format_writeprotected_at_start) ||
409
    (state == S_WAIT_FOR_FORMAT_INPUT && cmd_format_in_input_finish) ||
410
    cmd_get_status_start ||
411
    cmd_read_id_finished;
412
 
413
wire raise_interrupt = dma_irq_enable && (
414
    (cmd_read_write_start && (cmd_read_write_incorrect_head_at_start || cmd_read_write_incorrect_sector_at_start)) ||
415
    (cmd_write_normal_start && cmd_write_and_writeprotected_at_start) ||
416
    (state == S_CHECK_TC && (cmd_read_write_finish || cmd_format_finish)) ||
417
    (cmd_format_track_start && cmd_format_writeprotected_at_start) ||
418
    (state == S_WAIT_FOR_FORMAT_INPUT && cmd_format_in_input_finish) ||
419
    delay_last_cycle
420
);
421
 
422
wire reset_changeline =
423
    (cmd_read_write_ok_at_start) ||
424
    (state == S_UPDATE_SECTOR && increment_cylinder) ||
425
    (cmd_recalibrate_start && cylinder != 8'd0) ||
426
    (cmd_seek_start && cylinder != io_writedata);
427
 
428
 
429
//------------------------------------------------------------------------------ cmd: read / write
430
 
431
wire cmd_read_write_hang_at_start =
432
    ~(motor_enable) ||                  //motor off
433
    command[49:48] != 2'b00 ||          //no drive
434
    ~(media_present) ||                 //no media
435
    command[23:16] != 8'h02 ||          //invalid sector size
436
    command[47:40] >= media_cylinders;  //invalid cylinder
437
 
438
wire cmd_read_write_incorrect_head_at_start   = motor_enable && command[49:48] == 2'b00 && (command[50] != command[32] || (command[32] && media_heads == 2'd1));
439
wire cmd_read_write_incorrect_sector_at_start = ~(cmd_read_write_hang_at_start) && (command[31:24] > media_sectors_per_track || command[31:24] > command[15:8]);
440
wire cmd_write_and_writeprotected_at_start    = ~(cmd_read_write_hang_at_start) && ~(cmd_read_write_incorrect_sector_at_start) && cmd_write_normal_start && media_writeprotected;
441
 
442
wire cmd_read_write_ok_at_start =
443
    cmd_read_write_start && ~(cmd_read_write_hang_at_start) && ~(cmd_read_write_incorrect_head_at_start) && ~(cmd_read_write_incorrect_sector_at_start) && ~(cmd_write_and_writeprotected_at_start);
444
 
445
reg cmd_read_write_multitrack;
446
always @(posedge clk or negedge rst_n) begin
447
    if(rst_n == 1'b0)                   cmd_read_write_multitrack <= 1'b0;
448
    else if(cmd_read_write_ok_at_start) cmd_read_write_multitrack <= command[63];
449
end
450
 
451
wire cmd_read_write_finish =
452
    (cmd_read_normal_in_progress || cmd_write_normal_in_progress) && (
453
        (~(execute_ndma) && was_dma_terminal) ||
454
        (execute_ndma && cmd_read_write_was_ndma_terminal)
455
);
456
 
457
reg cmd_read_write_was_ndma_terminal;
458
always @(posedge clk or negedge rst_n) begin
459
    if(rst_n == 1'b0)                                                                               cmd_read_write_was_ndma_terminal <= 1'd0;
460
    else if(state == S_UPDATE_SECTOR && sector == eot && { 1'b0, head } == (media_heads - 2'd1))    cmd_read_write_was_ndma_terminal <= 1'd1;
461
    else if(state == S_UPDATE_SECTOR)                                                               cmd_read_write_was_ndma_terminal <= 1'd0;
462
end
463
 
464
//------------------------------------------------------------------------------ cmd: read id
465
 
466
wire cmd_read_id_hang_at_start =
467
    ~(motor_enable) ||                  //motor off
468
    io_writedata[1:0] != 2'b00 ||       //no drive
469
    ~(media_present);                   //no media
470
 
471
wire cmd_read_id_ok_at_start = cmd_read_id_start && ~(cmd_read_id_hang_at_start);
472
 
473
wire cmd_read_id_finished = state == S_WAIT && command_wait_counter == 16'd0 && cmd_read_id_in_progress;
474
 
475
//------------------------------------------------------------------------------ cmd: specify
476
 
477
reg [3:0] specify_srt;
478
always @(posedge clk or negedge rst_n) begin
479
    if(rst_n == 1'b0)           specify_srt <= 4'd0;
480
    else if(cmd_specify_start)  specify_srt <= command[7:4];
481
end
482
 
483
reg [3:0] specify_hut;
484
always @(posedge clk or negedge rst_n) begin
485
    if(rst_n == 1'b0)           specify_hut <= 4'b0;
486
    else if(cmd_specify_start)  specify_hut <= command[3:0];
487
end
488
 
489
reg [6:0] specify_hlt;
490
always @(posedge clk or negedge rst_n) begin
491
    if(rst_n == 1'b0)           specify_hlt <= 7'b0;
492
    else if(cmd_specify_start)  specify_hlt <= io_writedata[7:1];
493
end
494
 
495
reg ndma;
496
always @(posedge clk or negedge rst_n) begin
497
    if(rst_n == 1'b0)           ndma <= 1'b0;
498
    else if(cmd_specify_start)  ndma <= io_writedata[0];
499
end
500
 
501
//------------------------------------------------------------------------------ cmd: sense interrupt status
502
 
503
always @(posedge clk or negedge rst_n) begin
504
    if(rst_n == 1'b0)                                                   irq <= 1'b0;
505
    else if(sw_reset)                                                   irq <= 1'b1;
506
    else if(raise_interrupt)                                            irq <= 1'b1;
507
    else if(write_in_io_mode)                                           irq <= 1'b0;
508
    else if(read_in_io_mode)                                            irq <= 1'b0;
509
    else if(io_read_valid && io_address == 3'd5 && ~(read_in_io_mode))  irq <= 1'b0;
510
end
511
 
512
reg [2:0] reset_sensei;
513
always @(posedge clk or negedge rst_n) begin
514
    if(rst_n == 1'b0)                                                   reset_sensei <= 3'd0;
515
    else if(sw_reset)                                                   reset_sensei <= 3'd4;
516
    else if(raise_interrupt)                                            reset_sensei <= 3'd0;
517
    else if(cmd_sense_interrupt_status_start && reset_sensei > 3'd0)    reset_sensei <= reset_sensei - 3'd1;
518
end
519
 
520
wire [1:0] reset_sensei_drive =
521
    (reset_sensei == 3'd4)?     2'd0 :
522
    (reset_sensei == 3'd3)?     2'd1 :
523
    (reset_sensei == 3'd2)?     2'd2 :
524
                                2'd3;
525
 
526
reg pending_interrupt;
527
always @(posedge clk or negedge rst_n) begin
528
    if(rst_n == 1'b0)           pending_interrupt <= 1'b0;
529
    else if(raise_interrupt)    pending_interrupt <= 1'b1;
530
    else if(~(irq))             pending_interrupt <= 1'b0;
531
end
532
 
533
reg pending_interrupt_last;
534
always @(posedge clk or negedge rst_n) begin
535
    if(rst_n == 1'b0)   pending_interrupt_last <= 1'b0;
536
    else                pending_interrupt_last <= pending_interrupt;
537
end
538
 
539
//------------------------------------------------------------------------------ cmd: recalibrate / seek
540
 
541
reg [7:0] delay_steps;
542
always @(posedge clk or negedge rst_n) begin
543
    if(rst_n == 1'b0)                                                       delay_steps <= 8'd0;
544
    else if(cmd_recalibrate_start)                                          delay_steps <= (cylinder == 8'd0)? 8'd0 : cylinder - 8'd1;
545
    else if(cmd_seek_start)                                                 delay_steps <= (cylinder == io_writedata)? 8'd0 : (cylinder > io_writedata)? cylinder - io_writedata - 8'd1 : io_writedata - cylinder - 8'd1;
546
    else if(delay_rate == 16'd0 && delay_srt == 4'd0 && delay_steps > 8'd0) delay_steps <= delay_steps - 8'd1;
547
end
548
 
549
reg [3:0] delay_srt;
550
always @(posedge clk or negedge rst_n) begin
551
    if(rst_n == 1'b0)                                   delay_srt <= 4'd0;
552
    else if(cmd_recalibrate_start)                      delay_srt <= specify_srt;
553
    else if(cmd_seek_start)                             delay_srt <= specify_srt;
554
    else if(delay_rate == 16'd0 && delay_srt > 4'd0)    delay_srt <= delay_srt - 4'd1;
555
    else if(delay_rate == 16'd0 && delay_steps > 8'd0)  delay_srt <= specify_srt;
556
end
557
 
558
reg [15:0] delay_rate;
559
always @(posedge clk or negedge rst_n) begin
560
    if(rst_n == 1'b0)                               delay_rate <= 16'd0;
561
    else if(cmd_recalibrate_start)                  delay_rate <= (data_rate == 2'd0)? media_wait_rate_0 : (data_rate == 2'd1)? media_wait_rate_1 : (data_rate == 2'd2)? media_wait_rate_2 : media_wait_rate_3;
562
    else if(cmd_seek_start)                         delay_rate <= (data_rate == 2'd0)? media_wait_rate_0 : (data_rate == 2'd1)? media_wait_rate_1 : (data_rate == 2'd2)? media_wait_rate_2 : media_wait_rate_3;
563
    else if(delay_rate > 16'd0)                     delay_rate <= delay_rate - 16'd1;
564
    else if(delay_srt > 4'd0 || delay_steps > 8'd0) delay_rate <= (data_rate == 2'd0)? media_wait_rate_0 : (data_rate == 2'd1)? media_wait_rate_1 : (data_rate == 2'd2)? media_wait_rate_2 : media_wait_rate_3;
565
end
566
 
567
wire delay_last_cycle = delay_steps == 8'd0 && delay_srt == 4'd0 && delay_rate == 16'd1;
568
 
569
reg [7:0] status_reg0_temp;
570
always @(posedge clk or negedge rst_n) begin
571
    if(rst_n == 1'b0)                                                   status_reg0_temp <= 8'd0;
572
    else if(pending_interrupt && pending_interrupt_last == 1'b0)        status_reg0_temp <= reply[7:0];
573
    else if(cmd_sense_interrupt_status_start && reset_sensei > 3'd0)    status_reg0_temp <= { status_reg0_temp[7:3], (reset_sensei == 3'd4)? head : 1'b0, reset_sensei_drive };
574
end
575
 
576
//------------------------------------------------------------------------------ cmd: configure / lock / unlock
577
 
578
reg [7:0] config_config;
579
always @(posedge clk or negedge rst_n) begin
580
    if(rst_n == 1'b0)                   config_config <= 8'd0;
581
    else if(cmd_configure_mode_start)   config_config <= command[7:0];
582
end
583
 
584
reg [7:0] config_pretrk;
585
always @(posedge clk or negedge rst_n) begin
586
    if(rst_n == 1'b0)                   config_pretrk <= 8'd0;
587
    else if(cmd_configure_mode_start)   config_pretrk <= io_writedata;
588
end
589
 
590
reg [7:0] perp_mode;
591
always @(posedge clk or negedge rst_n) begin
592
    if(rst_n == 1'b0)                       perp_mode <= 8'd0;
593
    else if(cmd_perpendicular_mode_start)   perp_mode <= io_writedata;
594
end
595
 
596
reg lock;
597
always @(posedge clk or negedge rst_n) begin
598
    if(rst_n == 1'b0)           lock <= 1'd0;
599
    else if(cmd_unlock_start)   lock <= 1'd0;
600
    else if(cmd_lock_start)     lock <= 1'd1;
601
end
602
 
603
//------------------------------------------------------------------------------ cmd: format
604
 
605
wire cmd_format_writeprotected_at_start = ~(cmd_format_hang_on_start) && cmd_format_track_start && media_writeprotected;
606
 
607
wire cmd_format_hang_on_start =
608
    ~(motor_enable) ||                          //motor off
609
    command[25:24] != 2'b00 ||                  //no drive
610
    ~(media_present) ||                         //no media
611
    command[23:16] != 8'h02 ||                  //invalid sector size
612
    command[15:8] != media_sectors_per_track;   //invalid secotr count
613
 
614
wire cmd_format_ok_at_start = cmd_format_track_start && ~(cmd_format_writeprotected_at_start) && ~(cmd_format_hang_on_start);
615
 
616
reg [31:0] format_data;
617
always @(posedge clk or negedge rst_n) begin
618
    if(rst_n == 1'b0)                                       format_data <= 32'd0;
619
    else if(write_in_io_mode && format_data_count < 3'd4)   format_data <= { format_data[23:0], io_writedata };
620
    else if(dma_floppy_ack && format_data_count < 3'd4)     format_data <= { format_data[23:0], dma_floppy_readdata };
621
end
622
 
623
reg [2:0] format_data_count;
624
always @(posedge clk or negedge rst_n) begin
625
    if(rst_n == 1'b0)                                                           format_data_count <= 3'd0;
626
    else if(state != S_WAIT_FOR_FORMAT_INPUT)                                   format_data_count <= 3'd0;
627
    else if((write_in_io_mode || dma_floppy_ack) && format_data_count < 3'd4)   format_data_count <= format_data_count + 3'd1;
628
end
629
 
630
reg [7:0] format_filler_byte;
631
always @(posedge clk or negedge rst_n) begin
632
    if(rst_n == 1'b0)                   format_filler_byte <= 8'd0;
633
    else if(cmd_format_ok_at_start)     format_filler_byte <= io_writedata;
634
end
635
 
636
reg [7:0] format_sector_count;
637
always @(posedge clk or negedge rst_n) begin
638
    if(rst_n == 1'b0)                                                                               format_sector_count <= 8'd0;
639
    else if(cmd_format_ok_at_start)                                                                 format_sector_count <= command[15:8];
640
    else if(state == S_SD_FORMAT_WAIT_FOR_FILL && sd_read_counter == 9'd511 && sd_slave_read_valid) format_sector_count <= format_sector_count - 8'd1;
641
end
642
 
643
wire cmd_format_in_input_finish = ~(execute_ndma) && was_dma_terminal;
644
 
645
wire cmd_format_finish = cmd_format_in_progress && (
646
    cmd_format_in_input_finish ||
647
    (execute_ndma && format_sector_count == 8'd0)
648
);
649
 
650
//------------------------------------------------------------------------------ reply
651
 
652
reg [3:0] reply_left;
653
always @(posedge clk or negedge rst_n) begin
654
    if(rst_n == 1'b0)                                                               reply_left <= 4'd0;
655
    else if(sw_reset)                                                               reply_left <= 4'd0;
656
    else if(cmd_invalid_start)                                                      reply_left <= 4'd1;
657
    else if(cmd_read_write_start   && cmd_read_write_incorrect_head_at_start)       reply_left <= 4'd7;
658
    else if(cmd_read_write_start   && cmd_read_write_incorrect_sector_at_start)     reply_left <= 4'd7;
659
    else if(cmd_write_normal_start && cmd_write_and_writeprotected_at_start)        reply_left <= 4'd7;
660
    else if(cmd_format_track_start && cmd_format_writeprotected_at_start)           reply_left <= 4'd7;
661
    else if(state == S_CHECK_TC && (cmd_read_write_finish || cmd_format_finish))    reply_left <= 4'd7;
662
    else if(state == S_WAIT_FOR_FORMAT_INPUT && cmd_format_in_input_finish)         reply_left <= 4'd7;
663
    else if(cmd_read_id_finished)                                                   reply_left <= 4'd7;
664
    else if(cmd_get_status_start)                                                   reply_left <= 4'd1;
665
    else if(cmd_sense_interrupt_status_start)                                       reply_left <= 4'd2;
666
    else if(cmd_dump_registers_start)                                               reply_left <= 4'd10;
667
    else if(cmd_version_start)                                                      reply_left <= 4'd1;
668
    else if(cmd_unlock_start || cmd_lock_start)                                     reply_left <= 4'd1;
669
    else if(io_read_valid && io_address == 3'h5 && reply_left > 4'd0)               reply_left <= reply_left - 3'd1;
670
end
671
 
672
reg [79:0] reply;
673
always @(posedge clk or negedge rst_n) begin
674
    if(rst_n == 1'b0)                                                           reply <= 80'd0;
675
    else if(sw_reset)                                                           reply <= { 72'd0, 8'hC0 };
676
 
677
    else if(cmd_invalid_start)                                                  reply <= { reply[79:8], 8'h80 };
678
    else if(delay_last_cycle && cmd_recalibrate_in_progress)                    reply <= { reply[79:8], 8'h20 | { 6'd0, selected_drive[1:0] } | ((selected_drive != 2'd0 || ~(motor_enable))? 8'h50 : 8'h00) };
679
    else if(delay_last_cycle)                                                   reply <= { reply[79:8], 8'h20 | { 5'd0, (selected_drive != 2'd0)? 1'b0 : head, selected_drive[1:0] } };
680
    else if(cmd_read_write_start && cmd_read_write_incorrect_head_at_start)     reply <= { 24'd0, 8'd2, sector,         7'b0,head,         cylinder,       8'h00, 8'h04, (8'h40 | { 5'd0, head,        2'b0 }) };
681
    else if(cmd_read_write_start && cmd_read_write_incorrect_sector_at_start)   reply <= { 24'd0, 8'd2, command[31:24], 7'b0,command[32],  command[47:40], 8'h00, 8'h04, (8'h40 | { 5'd0, command[32], 2'b0 }) };
682
    else if(cmd_write_normal_start && cmd_write_and_writeprotected_at_start)    reply <= { 24'd0, 8'd2, command[31:24], 7'b0,command[32],  command[47:40], 8'h31, 8'h27, (8'h40 | { 5'd0, command[32], 2'b0 }) };
683
    else if(cmd_format_track_start && cmd_format_writeprotected_at_start)       reply <= { 24'd0, 8'd2, sector,         7'b0,command[26],  cylinder,       8'h31, 8'h27, (8'h40 | { 5'd0, command[26], 2'b0 }) };
684
    else if(state == S_CHECK_TC && cmd_read_write_finish)                       reply <= { 24'd0, 8'd2, sector,         7'b0,head,         cylinder,       8'h00, 8'h00, (8'h00 | { 5'd0, head,        2'b0 }) };
685
    else if(state == S_CHECK_TC && cmd_format_finish)                           reply <= { 24'd0, 8'd2, sector,         7'b0,head,         cylinder,       8'h00, 8'h00, (8'h00 | { 5'd0, head,        2'b0 }) };
686
    else if(state == S_WAIT_FOR_FORMAT_INPUT && cmd_format_in_input_finish)     reply <= { 24'd0, 8'd2, sector,         7'b0,head,         cylinder,       8'h00, 8'h00, (8'h40 | { 5'd0, head,        2'b0 }) };
687
    else if(cmd_read_id_finished)                                               reply <= { 24'd0, 8'd2, sector,         7'b0,head,         cylinder,       8'h00, 8'h00, (8'h00 | { 5'd0, head,        2'b0 }) };
688
    else if(cmd_get_status_start)                                               reply <= { 72'd0, 1'b0, media_writeprotected, 1'b1, (io_writedata[1:0] == 2'b00 && cylinder == 8'd0)? 1'b1 : 1'b0, 1'b1, io_writedata[2:0] };
689
    else if(cmd_sense_interrupt_status_start && reset_sensei > 3'd0)            reply <= { 64'd0, cylinder, status_reg0_temp[7:3], (reset_sensei == 3'd4)? head : 1'b0, reset_sensei_drive };
690
    else if(cmd_sense_interrupt_status_start && pending_interrupt)              reply <= { 64'd0, cylinder, status_reg0_temp };
691
    else if(cmd_sense_interrupt_status_start && ~(pending_interrupt))           reply <= { 64'd0, cylinder, 8'h80 };
692
    else if(cmd_dump_registers_start)                                           reply <= { config_pretrk, config_config, lock, perp_mode[6:0], (selected_drive == 2'd0)? eot : 8'd0,
693
                                                                                           specify_hlt, ndma, specify_srt, specify_hut, 8'h0, 8'h0, 8'h0, cylinder };
694
    else if(cmd_version_start)                                                  reply <= { 72'd0, 8'h90 };
695
    else if(cmd_unlock_start)                                                   reply <= 80'd0;
696
    else if(cmd_lock_start)                                                     reply <= { 72'd0, 3'd0, 1'b1, 4'd0 };
697
    else if(io_read_valid && io_address == 3'h5)                                reply <= { 8'd0, reply[79:8] };
698
end
699
 
700
//------------------------------------------------------------------------------ state
701
 
702
localparam [4:0] S_IDLE                         = 5'd0;
703
 
704
localparam [4:0] S_PREPARE_COUNT                = 5'd1;
705
localparam [4:0] S_COUNT_LOGICAL                = 5'd2;
706
 
707
localparam [4:0] S_SD_MUTEX                     = 5'd3;
708
localparam [4:0] S_SD_AVALON_BASE               = 5'd4;
709
localparam [4:0] S_SD_ADDRESS                   = 5'd5;
710
localparam [4:0] S_SD_BLOCK_COUNT               = 5'd6;
711
 
712
localparam [4:0] S_SD_CONTROL                   = 5'd7;
713
localparam [4:0] S_SD_READ_WAIT_FOR_DATA        = 5'd8;
714
localparam [4:0] S_WAIT_FOR_EMPTY_READ_FIFO     = 5'd9;
715
 
716
localparam [4:0] S_UPDATE_SECTOR                = 5'd10;
717
localparam [4:0] S_CHECK_TC                     = 5'd11;
718
localparam [4:0] S_WAIT                         = 5'd12;
719
 
720
localparam [4:0] S_WAIT_FOR_FULL_WRITE_FIFO     = 5'd13;
721
localparam [4:0] S_SD_WRITE_WAIT_FOR_EMPTY_FIFO = 5'd14;
722
 
723
localparam [4:0] S_WAIT_FOR_FORMAT_INPUT        = 5'd15;
724
localparam [4:0] S_SD_FORMAT_WAIT_FOR_FILL      = 5'd16;
725
 
726
reg [4:0] state;
727
always @(posedge clk or negedge rst_n) begin
728
    if(rst_n == 1'b0)                                                                                   state <= S_IDLE;
729
 
730
    //start read/write
731
    else if(state == S_IDLE && cmd_read_write_ok_at_start)                                              state <= S_PREPARE_COUNT;
732
 
733
    //read
734
    else if(state == S_COUNT_LOGICAL && mult_b == 8'd0 && cmd_read_normal_in_progress)                  state <= S_SD_MUTEX;
735
        //sd
736
    else if(state == S_SD_CONTROL && sd_master_waitrequest == 1'b0 && cmd_read_normal_in_progress)      state <= S_SD_READ_WAIT_FOR_DATA;
737
    else if(state == S_SD_READ_WAIT_FOR_DATA && sd_slave_write && sd_write_counter == 9'd511)           state <= S_WAIT_FOR_EMPTY_READ_FIFO;
738
    else if(state == S_WAIT_FOR_EMPTY_READ_FIFO && from_floppy_empty)                                   state <= S_UPDATE_SECTOR;
739
 
740
    //write
741
    else if(state == S_COUNT_LOGICAL && mult_b == 8'd0 && cmd_write_normal_in_progress)                 state <= S_WAIT_FOR_FULL_WRITE_FIFO;
742
    else if(state == S_WAIT_FOR_FULL_WRITE_FIFO && to_floppy_count == 11'd512)                          state <= S_SD_MUTEX;
743
        //sd
744
    else if(state == S_SD_CONTROL && sd_master_waitrequest == 1'b0 && cmd_write_normal_in_progress)     state <= S_SD_WRITE_WAIT_FOR_EMPTY_FIFO;
745
    else if(state == S_SD_WRITE_WAIT_FOR_EMPTY_FIFO && to_floppy_empty)                                 state <= S_UPDATE_SECTOR;
746
 
747
    //format
748
    else if(state == S_IDLE && cmd_format_ok_at_start)                                                  state <= S_WAIT_FOR_FORMAT_INPUT;
749
    else if(state == S_WAIT_FOR_FORMAT_INPUT && cmd_format_in_input_finish)                             state <= S_IDLE;
750
    else if(state == S_WAIT_FOR_FORMAT_INPUT && format_data_count == 3'd4)                              state <= S_PREPARE_COUNT;
751
        //count
752
    else if(state == S_COUNT_LOGICAL && mult_b == 8'd0 && cmd_format_in_progress)                       state <= S_SD_MUTEX;
753
        //sd
754
    else if(state == S_SD_CONTROL && sd_master_waitrequest == 1'b0 && cmd_format_in_progress)           state <= S_SD_FORMAT_WAIT_FOR_FILL;
755
    else if(state == S_SD_FORMAT_WAIT_FOR_FILL && sd_read_counter == 9'd511 && sd_slave_read_valid)     state <= S_WAIT;
756
 
757
    //read id
758
    else if(state == S_IDLE && cmd_read_id_ok_at_start)                                                 state <= S_WAIT;
759
    else if(state == S_WAIT && command_wait_counter == 16'd0 && cmd_read_id_in_progress)                state <= S_IDLE;
760
 
761
    //count
762
    else if(state == S_PREPARE_COUNT)                                                                   state <= S_COUNT_LOGICAL;
763
 
764
    //sd read/write
765
    else if(state == S_SD_MUTEX && sd_master_readdatavalid && sd_master_readdata[2:0] == 3'd1)          state <= S_SD_AVALON_BASE;
766
    else if(state == S_SD_AVALON_BASE && sd_master_waitrequest == 1'b0)                                 state <= S_SD_ADDRESS;
767
    else if(state == S_SD_ADDRESS     && sd_master_waitrequest == 1'b0)                                 state <= S_SD_BLOCK_COUNT;
768
    else if(state == S_SD_BLOCK_COUNT && sd_master_waitrequest == 1'b0)                                 state <= S_SD_CONTROL;
769
 
770
    //update read/write/format
771
    else if(state == S_UPDATE_SECTOR)                                                                   state <= S_WAIT;
772
    else if(state == S_WAIT && command_wait_counter == 16'd0 && ~(cmd_read_id_in_progress))             state <= S_CHECK_TC;
773
    else if(state == S_CHECK_TC && (cmd_read_write_finish || cmd_format_finish))                        state <= S_IDLE;
774
    else if(state == S_CHECK_TC && cmd_format_in_progress)                                              state <= S_WAIT_FOR_FORMAT_INPUT;
775
    else if(state == S_CHECK_TC)                                                                        state <= S_PREPARE_COUNT;
776
end
777
 
778
reg [15:0] command_wait_counter;
779
always @(posedge clk or negedge rst_n) begin
780
    if(rst_n == 1'b0)                                           command_wait_counter <= 16'd0;
781
    else if(state != S_WAIT)                                    command_wait_counter <= media_wait_cycles;
782
    else if(state == S_WAIT && command_wait_counter > 16'd0)    command_wait_counter <= command_wait_counter - 16'd1;
783
end
784
 
785
//------------------------------------------------------------------------------ count logical sector
786
 
787
reg [15:0] mult_a; //sectors per track * heads
788
always @(posedge clk or negedge rst_n) begin
789
    if(rst_n == 1'b0)                   mult_a <= 16'd0;
790
    else if(state == S_PREPARE_COUNT)   mult_a <= (media_heads == 2'd2)? { 7'd0, media_sectors_per_track, 1'b0 } : { 8'b0, media_sectors_per_track };
791
    else if(state == S_COUNT_LOGICAL)   mult_a <= { mult_a[14:0], 1'b0 };
792
end
793
 
794
reg [7:0] mult_b; //cylinder
795
always @(posedge clk or negedge rst_n) begin
796
    if(rst_n == 1'b0)                   mult_b <= 8'd0;
797
    else if(state == S_PREPARE_COUNT)   mult_b <= cylinder;
798
    else if(state == S_COUNT_LOGICAL)   mult_b <= { 1'b0, mult_b[7:1] };
799
end
800
 
801
reg [15:0] logical_sector;
802
always @(posedge clk or negedge rst_n) begin
803
    if(rst_n == 1'b0)                               logical_sector <= 16'd0;
804
    else if(state == S_PREPARE_COUNT)               logical_sector <= ((head == 1'b1)? { 8'd0, media_sectors_per_track } : 16'd0) + { 8'd0, sector } - 16'd1;
805
    else if(state == S_COUNT_LOGICAL && mult_b[0])  logical_sector <= logical_sector + mult_a;
806
end
807
 
808
//------------------------------------------------------------------------------ location
809
 
810
wire increment_only_sector = sector < eot && sector < media_sectors_per_track;
811
wire increment_cylinder    = ~(increment_only_sector) && (~(cmd_read_write_multitrack) || head == 1'b1);
812
 
813
reg [7:0] cylinder;
814
always @(posedge clk or negedge rst_n) begin
815
    if(rst_n == 1'b0)                                                                                                       cylinder <= 8'd0;
816
    else if(sw_reset)                                                                                                       cylinder <= 8'd0;
817
    else if(cmd_read_write_start && (cmd_read_write_incorrect_sector_at_start || cmd_write_and_writeprotected_at_start))    cylinder <= command[47:40];
818
    else if(cmd_read_write_ok_at_start)                                                                                     cylinder <= command[47:40];
819
    else if(cmd_recalibrate_start)                                                                                          cylinder <= 8'd0;
820
    else if(cmd_seek_start)                                                                                                 cylinder <= io_writedata;
821
    else if(state == S_UPDATE_SECTOR && increment_cylinder)                                                                 cylinder <= (cylinder >= media_cylinders)? media_cylinders - 8'd1 : cylinder + 8'd1;
822
    else if(state == S_WAIT_FOR_FORMAT_INPUT && format_data_count == 3'd4)                                                  cylinder <= format_data[31:24];
823
end
824
 
825
reg head;
826
always @(posedge clk or negedge rst_n) begin
827
    if(rst_n == 1'b0)                                                                                                       head <= 1'd0;
828
    else if(sw_reset)                                                                                                       head <= 1'b0;
829
    else if(cmd_read_write_start && (cmd_read_write_incorrect_sector_at_start || cmd_write_and_writeprotected_at_start))    head <= command[32];
830
    else if(cmd_format_track_start && cmd_format_writeprotected_at_start)                                                   head <= command[26];
831
    else if(cmd_read_write_ok_at_start)                                                                                     head <= command[32];
832
    else if(cmd_format_ok_at_start)                                                                                         head <= command[26];
833
    else if(cmd_get_status_start)                                                                                           head <= io_writedata[2];
834
    else if(cmd_seek_start)                                                                                                 head <= command[2];
835
    else if(cmd_read_id_start)                                                                                              head <= io_writedata[2];
836
    else if(state == S_UPDATE_SECTOR && ~(increment_only_sector) && cmd_read_write_multitrack)                              head <= ~(head);
837
end
838
 
839
reg [7:0] sector;
840
always @(posedge clk or negedge rst_n) begin
841
    if(rst_n == 1'b0)                                                                                                       sector <= 8'd1;
842
    else if(sw_reset)                                                                                                       sector <= 8'd1;
843
    else if(cmd_read_write_start && (cmd_read_write_incorrect_sector_at_start || cmd_write_and_writeprotected_at_start))    sector <= command[31:24];
844
    else if(cmd_read_write_ok_at_start)                                                                                     sector <= command[31:24];
845
    else if(state == S_UPDATE_SECTOR && increment_only_sector)                                                              sector <= sector + 8'd1;
846
    else if(state == S_UPDATE_SECTOR && ~(increment_only_sector))                                                           sector <= 8'd1;
847
    else if(state == S_WAIT_FOR_FORMAT_INPUT && format_data_count == 3'd4)                                                  sector <= format_data[15:8];
848
end
849
 
850
reg [7:0] eot;
851
always @(posedge clk or negedge rst_n) begin
852
    if(rst_n == 1'b0)                       eot <= 8'd0;
853
    else if(sw_reset)                       eot <= 8'd0;
854
    else if(cmd_read_write_ok_at_start)     eot <= (command[15:8] == 8'd0)? media_sectors_per_track : command[15:8];
855
end
856
 
857
//------------------------------------------------------------------------------ sd
858
 
859
assign sd_master_address =
860
    (state == S_SD_MUTEX)?          32'd4 :
861
    (state == S_SD_AVALON_BASE)?    32'd0 :
862
    (state == S_SD_ADDRESS)?        32'd4 :
863
    (state == S_SD_BLOCK_COUNT)?    32'd8 :
864
    (state == S_SD_CONTROL)?        32'd12 :
865
                                    32'd0;
866
 
867
reg [2:0] sd_mutex_wait;
868
always @(posedge clk or negedge rst_n) begin
869
    if(rst_n == 1'b0)                                       sd_mutex_wait <= 3'd0;
870
    else if(state == S_SD_MUTEX && sd_master_read == 1'b0)  sd_mutex_wait <= sd_mutex_wait + 3'd1;
871
end
872
 
873
reg sd_read_done;
874
always @(posedge clk or negedge rst_n) begin
875
    if(rst_n == 1'b0)                                           sd_read_done <= 1'b0;
876
    else if(sd_master_read && sd_master_waitrequest == 1'b0)    sd_read_done <= 1'b1;
877
    else if(sd_master_readdatavalid)                            sd_read_done <= 1'b0;
878
end
879
 
880
assign sd_master_read = state == S_SD_MUTEX && sd_mutex_wait == 3'd5 && ~(sd_read_done);
881
 
882
assign sd_master_write = state == S_SD_AVALON_BASE || state == S_SD_ADDRESS || state == S_SD_BLOCK_COUNT || state == S_SD_CONTROL;
883
 
884
assign sd_master_writedata =
885
    (state == S_SD_AVALON_BASE)?                                `SD_AVALON_BASE_ADDRESS_FOR_FDD :
886
    (state == S_SD_ADDRESS)?                                    sd_sector :
887
    (state == S_SD_BLOCK_COUNT)?                                32'd1 :
888
    (state == S_SD_CONTROL && cmd_read_normal_in_progress)?     32'd2 : //CONTROL_READ
889
    (state == S_SD_CONTROL && cmd_write_normal_in_progress)?    32'd3 : //CONTROL_WRITE
890
    (state == S_SD_CONTROL && cmd_format_in_progress)?          32'd3 : //CONTROL_WRITE
891
                                                                32'd0;
892
 
893
reg [8:0] sd_write_counter;
894
always @(posedge clk or negedge rst_n) begin
895
    if(rst_n == 1'b0)           sd_write_counter <= 9'd0;
896
    else if(sd_slave_write)     sd_write_counter <= sd_write_counter + 9'd1;
897
end
898
 
899
reg [8:0] sd_read_counter;
900
always @(posedge clk or negedge rst_n) begin
901
    if(rst_n == 1'b0)               sd_read_counter <= 9'd0;
902
    else if(sd_slave_read_valid)    sd_read_counter <= sd_read_counter + 9'd1;
903
end
904
 
905
reg [31:0] sd_sector;
906
always @(posedge clk or negedge rst_n) begin
907
    if(rst_n == 1'b0)                   sd_sector <= 32'd0;
908
    else if(state == S_SD_AVALON_BASE)  sd_sector <= ({ 16'd0, logical_sector } >= media_sector_count)? media_sd_base + media_sector_count - 32'd1 : media_sd_base + { 16'd0, logical_sector };
909
end
910
 
911
//------------------------------------------------------------------------------ dma
912
 
913
assign dma_floppy_writedata = from_floppy_q;
914
 
915
assign dma_floppy_req = ~(execute_ndma) && ~(was_dma_terminal) && dma_irq_enable && ~(dma_floppy_ack) && (
916
    (cmd_read_normal_in_progress  && ~(from_floppy_empty) && state == S_WAIT_FOR_EMPTY_READ_FIFO) ||
917
    (cmd_write_normal_in_progress && to_floppy_count <= 11'd511 && state == S_WAIT_FOR_FULL_WRITE_FIFO) ||
918
    (cmd_format_in_progress       && format_data_count < 3'd4 && state == S_WAIT_FOR_FORMAT_INPUT)
919
);
920
 
921
reg was_dma_terminal;
922
always @(posedge clk or negedge rst_n) begin
923
    if(rst_n == 1'b0)               was_dma_terminal <= 1'd0;
924
    else if(state == S_IDLE)        was_dma_terminal <= 1'd0;
925
    else if(dma_floppy_terminal)    was_dma_terminal <= 1'd1;
926
end
927
 
928
//------------------------------------------------------------------------------ fifo
929
 
930
wire [10:0] to_floppy_count = { to_floppy_full, to_floppy_usedw };
931
wire [9:0]  to_floppy_usedw;
932
wire        to_floppy_full;
933
wire        to_floppy_empty;
934
wire [7:0]  to_floppy_q;
935
 
936
always @(posedge clk or negedge rst_n) begin
937
    if(rst_n == 1'b0)                   sd_slave_readdata <= 8'b0;
938
    else if(cmd_format_in_progress)     sd_slave_readdata <= format_filler_byte;
939
    else                                sd_slave_readdata <= to_floppy_q;
940
end
941
 
942
simple_fifo #(
943
    .width      (8),
944
    .widthu     (10)
945
)
946
fifo_to_floppy_inst(
947
    .clk        (clk),
948
    .rst_n      (rst_n),
949
 
950
    .sclr       (state == S_IDLE), //input
951
 
952
    .data       ((execute_ndma)? io_writedata : (was_dma_terminal)? 8'h00 : dma_floppy_readdata),                                                                                           //input [7:0]
953
    .wrreq      (state == S_WAIT_FOR_FULL_WRITE_FIFO && (write_in_io_mode || (~(execute_ndma) && dma_floppy_ack) || (~(execute_ndma) && was_dma_terminal)) && to_floppy_count < 11'd512),   //input
954
    .full       (to_floppy_full),   //output
955
 
956
    .rdreq      (sd_slave_read_valid),  //input
957
    .empty      (to_floppy_empty),      //output
958
    .q          (to_floppy_q),          //output [7:0]
959
 
960
    .usedw      (to_floppy_usedw)       //output [9:0]
961
);
962
 
963
wire [7:0] from_floppy_q;
964
wire       from_floppy_empty;
965
 
966
simple_fifo #(
967
    .width      (8),
968
    .widthu     (10)
969
)
970
fifo_from_floppy_inst(
971
    .clk        (clk),
972
    .rst_n      (rst_n),
973
 
974
     .sclr      (state == S_IDLE || (state == S_WAIT_FOR_EMPTY_READ_FIFO && ~(execute_ndma) && dma_floppy_terminal)),   //input
975
 
976
    .data       (sd_slave_writedata),   //input [7:0]
977
    .wrreq      (sd_slave_write),       //input
978
 
979
    .rdreq      (state == S_WAIT_FOR_EMPTY_READ_FIFO && (read_in_io_mode || (~(execute_ndma) && dma_floppy_ack))),      //input
980
    .empty      (from_floppy_empty),    //output
981
    .q          (from_floppy_q),        //output [7:0]
982
 
983
    /* verilator lint_off PINNOCONNECT */
984
    .full       (),                     //output
985
    .usedw      ()                      //output [9:0]
986
    /* verilator lint_on PINNOCONNECT */
987
);
988
 
989
//------------------------------------------------------------------------------
990
 
991
// synthesis translate_off
992
wire _unused_ok = &{ 1'b0, sd_master_readdata[31:3], sd_slave_address, command[71:64], perp_mode[7], 1'b0 };
993
// synthesis translate_on
994
 
995
//------------------------------------------------------------------------------
996
 
997
endmodule

powered by: WebSVN 2.1.0

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