Приложение 4
module audiocodec (input start, input clk, input AUD_DACLRCK, input AUD_BCLK,
output AUD_DACDAT, output I2C_SCLK, inout I2C_SDAT, output [3:0] led);
reg [4:0] ima_index_table [0:7];
reg [14:0] ima_step_table [0:88];
reg start_i2c=1'b0;
reg [8:0] data=9'b0;
reg [6:0] addr=6'b0;
reg [15:0] vol=16'b0;
reg [4:0] state=5'b0000;
reg [1:0] LRC=2'b00;
reg [3:0] i=4'b1111;
reg lg=1'b0;
reg lgg=1'b0;
reg f=1'b0;
reg g=1'b0;
reg [15:0] sample=16'b1000_0000_0000_0000;
reg [15:0] newsample=16'b0;
reg [6:0] step_index=7'b0;
reg [6:0] step_index_prev=7'b0;
reg [1:0] decode_state=2'b00;
wire done;
wire [3:0] wmus;
wire [14:0] step;
wire [4:0] index;
assign step=ima_step_table[step_index];
assign index=ima_index_table[wmus[2:0]];
assign led[3]=lg;
assign led[2]=lgg;
assign AUD_DACDAT=start?sample[i]:1'b0;
initial begin
$readmemb("ima_index_table.txt",ima_index_table);
$readmemh("ima_step_table.txt",ima_step_table);
end
always @(posedge clk)
case (state)
5'b00000: //Power Down Control: enable device, line output, DAC
begin
addr<=7'b0000110;
data<=9'b001100111;
start_i2c<=1'b1;
state<=state+1;
end
5'b00001:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b00010: //Analogue Audio Path Control: DAC Select=1
if (done)
begin
addr<=7'b0000100;
data<=9'b000010000;
start_i2c<=1'b1;
state<=state+1;
end
5'b00011:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b00100:
if (done) //Digital Audio Interface Format: Master Mode, DSP Mode A, 16 bits
begin
addr<=7'b0000111;
data<=9'b001010011;
start_i2c<=1'b1;
state<=state+1;
end
5'b00101:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b00110: //Active Control: ACTIVE=0
if (done)
begin
addr<=7'b0001001;
data<=9'b000000000;
start_i2c<=1'b1;
state<=state+1;
end
5'b00111:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01000: //Active Control: ACTIVE=1
if (done)
begin
addr<=7'b0001001;
data<=9'b000000001;
start_i2c<=1'b1;
state<=state+1;
end
5'b01001:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01010:
if (done) //Sampling Control: DAC - 8 kHz, use 12 MHz MCLK, USB Mode, MCLK divided by 2
begin
addr<=7'b0001000;
data<=9'b001001101; //9'b001101011; 41 kHz //9'b001001101 8 kHz // 9'b001011001 // 32 kHz
start_i2c<=1'b1;
state<=state+1;
end
5'b01011:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01100: //Active Control: ACTIVE=0
if (done)
begin
addr<=7'b0001001;
data<=9'b000000000;
start_i2c<=1'b1;
state<=state+1;
end
5'b01101:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b01110: //Active Control: ACTIVE=1
if (done)
begin
addr<=7'b0001001;
data<=9'b000000001;
start_i2c<=1'b1;
state<=state+1;
end
5'b01111:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b10000: // LZCEN=1
if (done)
begin
addr<=7'b0000010;
data<=9'b0011111001;
start_i2c<=1'b1;
state<=state+1;
end
5'b10001:
begin
start_i2c<=1'b0;
state<=state+1;
end
5'b10010: // RZCEN=1
if (done)
begin
addr<=7'b0000011;
data<=9'b0011111001;
start_i2c<=1'b1;
state<=state+1;
end
5'b10011:
begin
start_i2c<=1'b0;
lg<=1'b1;
end
endcase
always @(negedge AUD_BCLK)
if (start)
begin
case (decode_state)
2'b00:
begin
newsample<={{4{1'b0}},step[14:3]}+(wmus[0]?{{3{1'b0}},step[14:2]}:16'b0)+(wmus[1]?{{2{1'b0}},step[14:1]}:16'b0)+(wmus[2]?{{2{1'b0}},step}:16'b0);
decode_state<=decode_state+1;
end
2'b01:
begin
if (wmus[3])
begin
if (newsample>sample)
newsample<=16'b0;
else
newsample<=sample-newsample;
end
else
begin
if (newsample>(16'b1111_1111_1111_1111 - sample))
newsample<=16'b1111_1111_1111_1111;
else
newsample<=sample+newsample;
end
if (index[4])
begin
if (step_index>7'b0)
step_index<=step_index-1;
end
else
begin
if ((step_index+index)>88)
step_index<=88;
else
step_index<=step_index+index;
end
decode_state<=decode_state+1;
end
endcase
if (i>0)
i<=i-1;
if (i==0&!f)
begin
if (g)
begin
vol<=vol+1;
decode_state<=2'b00;
step_index_prev<=step_index;
step_index<=step_index_prev;
sample<=newsample;
end
f<=1'b1;
i<=4'b1111;
end
if (LRC[0]&!LRC[1])
begin
lgg<=1'b1;
decode_state<=2'b00;
i<=4'b1111;
f<=1'b0;
if (vol<59903)
begin
sample<=newsample;
step_index_prev<=step_index;
step_index<=step_index_prev;
g<=1'b1;
if (g)
begin
vol<=vol+1;
end
end
else
begin
step_index_prev<=7'b0;
step_index<=7'b0;
g<=1'b0;
sample<=16'b1000_0000_0000_0000;
vol<=16'b0;
end
end
end
else
begin
step_index_prev<=7'b0;
decode_state<=2'b00;
g<=1'b0;
f<=1'b0;
step_index<=7'b0;
sample<=16'b1000_0000_0000_0000;
i<=4'b1111;
vol<=16'b0;
end
always @(posedge AUD_BCLK)
begin
LRC[0]<=AUD_DACLRCK;
LRC[1]<=LRC[0];
end
i2c toaud (.start(start_i2c),
.clk50(clk),
.data(data),
.addr(addr),
.I2C_SCLK(I2C_SCLK),
.I2C_SDAT(I2C_SDAT),
.done(done),
.led(led[1:0]));
ROM r(.address(vol),
.clock(clk),
.q(wmus));
endmodule
