134 lines
3.1 KiB
Systemverilog
134 lines
3.1 KiB
Systemverilog
//============================================================================
|
|
//
|
|
// ALSA sound support for MiSTer
|
|
// (c)2019 Sorgelig
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
// more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
//
|
|
//============================================================================
|
|
|
|
module alsa
|
|
(
|
|
input reset,
|
|
|
|
output reg en_out,
|
|
input en_in,
|
|
|
|
input ram_clk,
|
|
output reg [28:0] ram_address,
|
|
output reg [7:0] ram_burstcount,
|
|
input ram_waitrequest,
|
|
input [63:0] ram_readdata,
|
|
input ram_readdatavalid,
|
|
output reg ram_read,
|
|
|
|
input spi_ss,
|
|
input spi_sck,
|
|
input spi_mosi,
|
|
|
|
output reg [15:0] pcm_l,
|
|
output reg [15:0] pcm_r
|
|
);
|
|
|
|
reg spi_new = 0;
|
|
reg [127:0] spi_data;
|
|
always @(posedge spi_sck, posedge spi_ss) begin
|
|
reg [7:0] mosi;
|
|
reg [6:0] spicnt = 0;
|
|
|
|
if(spi_ss) spicnt <= 0;
|
|
else begin
|
|
mosi <= {mosi[6:0],spi_mosi};
|
|
|
|
spicnt <= spicnt + 1'd1;
|
|
if(&spicnt[2:0]) begin
|
|
spi_data[{spicnt[6:3],3'b000} +:8] <= {mosi[6:0],spi_mosi};
|
|
spi_new <= &spicnt;
|
|
end
|
|
end
|
|
end
|
|
|
|
reg [31:0] buf_addr;
|
|
reg [31:0] buf_len;
|
|
reg [31:0] buf_wptr = 0;
|
|
|
|
always @(posedge ram_clk) begin
|
|
reg n1,n2,n3;
|
|
reg [127:0] data1,data2;
|
|
|
|
n1 <= spi_new;
|
|
n2 <= n1;
|
|
n3 <= n2;
|
|
|
|
data1 <= spi_data;
|
|
data2 <= data1;
|
|
|
|
if(~n3 & n2) {buf_wptr,buf_len,buf_addr} <= data2[95:0];
|
|
end
|
|
|
|
reg [31:0] buf_rptr = 0;
|
|
always @(posedge ram_clk) begin
|
|
reg got_first = 0;
|
|
reg ready = 0;
|
|
reg ud = 0;
|
|
reg [31:0] readdata;
|
|
|
|
if(~ram_waitrequest) ram_read <= 0;
|
|
if(ram_readdatavalid && ram_burstcount) begin
|
|
ram_burstcount <= 0;
|
|
ready <= 1;
|
|
readdata <= ud ? ram_readdata[63:32] : ram_readdata[31:0];
|
|
if(buf_rptr[31:2] >= buf_len[31:2]) buf_rptr <= 0;
|
|
end
|
|
|
|
if(reset) {ready, got_first, ram_burstcount} <= 0;
|
|
else
|
|
if(buf_rptr[31:2] != buf_wptr[31:2]) begin
|
|
if(~got_first) begin
|
|
buf_rptr <= buf_wptr;
|
|
got_first <= 1;
|
|
end
|
|
else
|
|
if(!ram_burstcount && ~ram_waitrequest && ~ready && en_out == en_in) begin
|
|
ram_address <= buf_addr[31:3] + buf_rptr[31:3];
|
|
ud <= buf_rptr[2];
|
|
ram_burstcount <= 1;
|
|
ram_read <= 1;
|
|
buf_rptr <= buf_rptr + 4;
|
|
end
|
|
end
|
|
|
|
if(ready & ce_48k) begin
|
|
{pcm_r,pcm_l} <= readdata;
|
|
ready <= 0;
|
|
end
|
|
|
|
if(ce_48k) en_out <= ~en_out;
|
|
end
|
|
|
|
reg ce_48k;
|
|
always @(posedge ram_clk) begin
|
|
reg [15:0] acc = 0;
|
|
|
|
ce_48k <= 0;
|
|
acc <= acc + 16'd48;
|
|
if(acc >= 50000) begin
|
|
acc <= acc - 16'd50000;
|
|
ce_48k <= 1;
|
|
end
|
|
end
|
|
|
|
endmodule
|