module tap
(
input wire reset_n,
input wire clock,
input wire play,
output reg mic,
output reg [15:0] tap_address,
input wire [7:0] tap_data
);
`ifdef ICARUS
parameter
PILOT_PERIOD = 4,
PILOT_HEADER = 6,
PILOT_DATA = 3,
SYNC_HI = 4,
SYNC_LO = 3,
SIGNAL_0 = 2,
SIGNAL_1 = 4;
`else
parameter
PILOT_PERIOD = 2168,
PILOT_HEADER = 8064,
PILOT_DATA = 3224,
SYNC_HI = 667,
SYNC_LO = 735,
SIGNAL_0 = 855,
SIGNAL_1 = 1710;
`endif
reg [ 3:0] state = 0;
reg [11:0] cnt = 0;
reg [12:0] pilot = 0;
reg [15:0] length = 0;
reg [10:0] hdata = 0;
reg [10:0] ldata = 0;
reg [ 2:0] bitn = 0;
reg [20:0] delay = 0;
reg block = 0;
initial tap_address = 0;
always @(posedge clock) begin
if (!reset_n)
begin
state <= 0;
mic <= 1;
tap_address <= 0;
end
else case (state)
0: begin state <= play ? 1 : 0; mic <= 1; end
1: begin state <= 2; length[ 7:0] <= tap_data; tap_address <= tap_address + 1; end
2: begin state <= 3; length[15:8] <= tap_data; tap_address <= tap_address + 1; end
3: begin
state <= length ? 4 : 15;
block <= tap_data[7];
pilot <= tap_data[7] ? PILOT_DATA : PILOT_HEADER;
delay <= 1750000;
bitn <= 7;
cnt <= 0;
end
4: begin
cnt <= cnt + 1;
if (cnt == PILOT_PERIOD-1)
begin
cnt <= 0;
mic <= ~mic;
pilot <= pilot - 1;
if (pilot == 1) begin state <= 5; cnt <= SYNC_HI; end
end
end
5: begin mic <= 1; cnt <= cnt - 1; state <= (cnt == 2) ? 6 : 5; end
6: begin mic <= 0; cnt <= cnt + 1; state <= (cnt == SYNC_LO) ? 7 : 6; end
7: begin
mic <= 1;
bitn <= bitn - 1;
state <= 8;
hdata <= tap_data[ bitn ] ? SIGNAL_1 : SIGNAL_0;
ldata <= tap_data[ bitn ] ? SIGNAL_1 : SIGNAL_0;
if (bitn == 7 && length == 0)
state <= (block ? 0 : 10);
if (bitn == 0) begin
length <= length - 1;
tap_address <= tap_address + 1;
end
end
8: begin mic <= 1; state <= hdata == 2 ? 9 : 8; hdata <= hdata - 1; end
9: begin mic <= 0; state <= ldata == 1 ? 7 : 9; ldata <= ldata - 1; end
10: if (delay) delay <= delay - 1; else state <= 1;
endcase
end
endmodule