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

Subversion Repositories floppyif

[/] [floppyif/] [trunk/] [rtl/] [mfm_read.v] - Blame information for rev 4

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jhallen
// MFM reader
2
 
3
module mfm_read
4
  (
5
  input reset_l,
6
 
7
  // 24 MHz clock
8
 
9
  input clk,
10
 
11
  // Read pulses in
12
 
13
  input read_pulse_l,
14
 
15
  // Decoded bytes out
16
 
17
  output reg [7:0] data_out,     // Data byte
18
  output reg mark,              // Set if byte is an address mark
19
  output reg valid,             // Set if valid
20
  output reg crc_zero           // Set if CRC is 0 (meaning no errors) after this byte
21
  );
22
 
23
// Clock/Data separator
24
 
25
parameter PERIOD = (24 * 256);
26
// No. clocks per period * 256 (one period is 1/2 bit time: 1us for MFM)
27
 
28
parameter HALF = (PERIOD / 2);
29
 
30
reg [12:0] count;        // Bit window timer
31
 
32
reg capture;            // Set if bit was found in this window
33
 
34
reg [2:0] leading;       // Synchronizer and leading edge detector
35
 
36
reg sep_clock;
37
reg sep_data;
38
 
39
reg [12:0] adjust; // Amount to add to clock
40
 
41
always @(posedge clk or negedge reset_l)
42
  if (!reset_l)
43
    begin
44
      leading <= 3'b111;
45
      capture <= 0;
46
      count <= 0;
47
      sep_clock <= 0;
48
      sep_data <= 0;
49
    end
50
  else
51
    begin
52
      sep_clock <= 0;
53
 
54
      // Feed leading edge detector
55
      leading <= { read_pulse_l, leading[2:1] };
56
 
57
      // Normal counter increment
58
      adjust = 256;
59
 
60
      // We detect an edge
61
      if (!leading[1] && leading[0])
62
        begin
63
          // Note that edge was detected
64
          capture <= 1;
65
 
66
          // Bump counter: it should be at HALF
67
          if (count > HALF)
68
            // We're too fast: retard
69
            adjust = 256 - ((count-HALF)>>1);
70
          else if (count < HALF)
71
            // We're too slow: advance
72
            adjust = 256 + ((count-HALF)>>1);
73
        end
74
 
75
      // Advance clock
76
      if (count + adjust >= PERIOD)
77
        begin
78
          count <= count + adjust - PERIOD;
79
          capture <= 0;
80
          sep_clock <= 1;
81
          sep_data <= capture;
82
        end
83
      else
84
        count <= count + adjust;
85
 
86
    end
87
 
88
// Address mark detector, byte aligner
89
 
90
reg [15:0] shift_reg;    // Shift register
91
reg [3:0] shift_count;
92
 
93
// Data bits
94
 
95
wire [7:0] data = { shift_reg[14], shift_reg[12], shift_reg[10], shift_reg[8],
96
                    shift_reg[6], shift_reg[4], shift_reg[2], shift_reg[0] };
97
 
98
// Clock bits
99
 
100
wire [7:0] clock = { shift_reg[15], shift_reg[13], shift_reg[11], shift_reg[9],
101
                     shift_reg[7], shift_reg[5], shift_reg[3], shift_reg[1] };
102
 
103
reg [7:0] aligned_byte;
104
reg aligned_valid;
105
reg aligned_mark;
106
 
107
always @(posedge clk or negedge reset_l)
108
  if(!reset_l)
109
    begin
110
      shift_reg <= 0;
111
      shift_count <= 0;
112
      aligned_mark <= 0;
113
      aligned_byte <= 0;
114
      aligned_valid <= 0;
115
    end
116
  else
117
    begin
118
      aligned_valid <= 0;
119
      if(sep_clock)
120
        begin
121
          shift_reg <= { shift_reg[14:0], sep_data };
122
 
123
          if(shift_count)
124
            shift_count <= shift_count - 1;
125
 
126
          if(clock==8'h0A && data==8'hA1 || !shift_count)
127
            begin
128
              shift_count <= 15;
129
              aligned_byte <= data;
130
              aligned_valid <= 1;
131
              if(clock==8'h0A && data==8'hA1)
132
                aligned_mark <= 1;
133
              else
134
                aligned_mark <= 0;
135
            end
136
        end
137
    end
138
 
139
// CRC checker
140
 
141
function [15:0] crc;
142
input [15:0] accu;
143
input [7:0] byte;
144
  begin
145
    crc[0] = accu[4'h8]^accu[4'hC]^byte[4]^byte[0];
146
    crc[1] = accu[4'h9]^accu[4'hD]^byte[5]^byte[1];
147
    crc[2] = accu[4'hA]^accu[4'hE]^byte[6]^byte[2];
148
    crc[3] = accu[4'hB]^accu[4'hF]^byte[7]^byte[3];
149
    crc[4] = accu[4'hC]^byte[4];
150
    crc[5] = accu[4'hD]^byte[5]^accu[4'h8]^accu[4'hC]^byte[4]^byte[0];
151
    crc[6] = accu[4'hE]^byte[6]^accu[4'h9]^accu[4'hD]^byte[5]^byte[1];
152
    crc[7] = accu[4'hF]^byte[7]^accu[4'hA]^accu[4'hE]^byte[6]^byte[2];
153
    crc[8] = accu[4'h0]^accu[4'hB]^accu[4'hF]^byte[7]^byte[3];
154
    crc[9] = accu[4'h1]^accu[4'hC]^byte[4];
155
    crc[10] = accu[4'h2]^accu[4'hD]^byte[5];
156
    crc[11] = accu[4'h3]^accu[4'hE]^byte[6];
157
    crc[12] = accu[4'h4]^accu[4'hF]^byte[7]^accu[4'h8]^accu[4'hC]^byte[4]^byte[0];
158
    crc[13] = accu[4'h5]^accu[4'h9]^accu[4'hD]^byte[5]^byte[1];
159
    crc[14] = accu[4'h6]^accu[4'hA]^accu[4'hE]^byte[6]^byte[2];
160
    crc[15] = accu[4'h7]^accu[4'hB]^accu[4'hF]^byte[7]^byte[3];
161
  end
162
endfunction
163
 
164
reg [15:0] fcs;
165
reg [2:0] count;
166
 
167
always @(posedge clk or negedge reset_l)
168
  if(!reset_l)
169
    begin
170
      fcs <= 0;
171
      count <= 0;
172
      data_out <= 0;
173
      mark <= 0;
174
      valid <= 0;
175
      crc_zero <= 0;
176
    end
177
  else
178
    begin
179
      if(aligned_valid)
180
        begin
181
          data_out <= aligned_data;
182
          valid <= 1;
183
          mark <= aligned_mark;
184
 
185
          fcs <= compute_fcs(fcs, aligned_byte);
186
          crc_zero <= (compute_fcs(fcs, aligned_byte)==16'h0000);
187
 
188
          // Ignore address marks after the first one
189
          if(count)
190
            count <= count - 1;
191
          else if(aligned_mark)
192
            begin
193
              // Start of packet: initial crc
194
              fcs <= compute_fcs(16'hFFFF, aligned_byte);
195
              count <= 4;
196
            end
197
        end
198
      else
199
        valid <= 0;
200
    end
201
 
202
endmodule

powered by: WebSVN 2.1.0

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