mirror of
https://github.com/MiSTer-devel/MacPlus_MiSTer.git
synced 2024-11-27 02:49:32 +00:00
158 lines
3.7 KiB
Systemverilog
158 lines
3.7 KiB
Systemverilog
//============================================================================
|
|
//
|
|
// ALSA sound support for MiSTer
|
|
// (c)2019,2020 Alexey Melnikov
|
|
//
|
|
// 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
|
|
#(
|
|
parameter CLK_RATE = 24576000
|
|
)
|
|
(
|
|
input reset,
|
|
input clk,
|
|
|
|
output reg [31:3] ram_address,
|
|
input [63:0] ram_data,
|
|
output reg ram_req = 0,
|
|
input ram_ready,
|
|
|
|
input spi_ss,
|
|
input spi_sck,
|
|
input spi_mosi,
|
|
output spi_miso,
|
|
|
|
output reg [15:0] pcm_l,
|
|
output reg [15:0] pcm_r
|
|
);
|
|
|
|
reg [60:0] buf_info;
|
|
reg [6:0] spicnt = 0;
|
|
always @(posedge spi_sck, posedge spi_ss) begin
|
|
reg [95:0] spi_data;
|
|
|
|
if(spi_ss) spicnt <= 0;
|
|
else begin
|
|
spi_data[{spicnt[6:3],~spicnt[2:0]}] <= spi_mosi;
|
|
if(&spicnt) buf_info <= {spi_data[82:67],spi_data[50:35],spi_data[31:3]};
|
|
spicnt <= spicnt + 1'd1;
|
|
end
|
|
end
|
|
|
|
assign spi_miso = spi_out[{spicnt[4:3],~spicnt[2:0]}];
|
|
|
|
reg [31:0] spi_out = 0;
|
|
always @(posedge clk) if(spi_ss) spi_out <= {buf_rptr, hurryup, 8'h00};
|
|
|
|
|
|
reg [31:3] buf_addr;
|
|
reg [18:3] buf_len;
|
|
reg [18:3] buf_wptr = 0;
|
|
|
|
always @(posedge clk) begin
|
|
reg [60:0] data1,data2;
|
|
|
|
data1 <= buf_info;
|
|
data2 <= data1;
|
|
if(data2 == data1) {buf_wptr,buf_len,buf_addr} <= data2;
|
|
end
|
|
|
|
reg [2:0] hurryup = 0;
|
|
reg [18:3] buf_rptr = 0;
|
|
|
|
always @(posedge clk) begin
|
|
reg [18:3] len = 0;
|
|
reg [1:0] ready = 0;
|
|
reg [63:0] readdata;
|
|
reg got_first = 0;
|
|
reg [7:0] ce_cnt = 0;
|
|
reg [1:0] state = 0;
|
|
|
|
if(reset) begin
|
|
ready <= 0;
|
|
ce_cnt <= 0;
|
|
state <= 0;
|
|
got_first <= 0;
|
|
len <= 0;
|
|
end
|
|
else begin
|
|
|
|
//ramp up
|
|
if(len[18:14] && (hurryup < 1)) hurryup <= 1;
|
|
if(len[18:16] && (hurryup < 2)) hurryup <= 2;
|
|
if(len[18:17] && (hurryup < 4)) hurryup <= 4;
|
|
|
|
//ramp down
|
|
if(!len[18:15] && (hurryup > 2)) hurryup <= 2;
|
|
if(!len[18:13] && (hurryup > 1)) hurryup <= 1;
|
|
if(!len[18:10]) hurryup <= 0;
|
|
|
|
if(ce_sample && ~&ce_cnt) ce_cnt <= ce_cnt + 1'd1;
|
|
|
|
case(state)
|
|
0: if(!ce_sample) begin
|
|
if(ready) begin
|
|
if(ce_cnt) begin
|
|
{readdata[31:0],pcm_r,pcm_l} <= readdata;
|
|
ready <= ready - 1'd1;
|
|
ce_cnt <= ce_cnt - 1'd1;
|
|
end
|
|
end
|
|
else if(buf_rptr != buf_wptr) begin
|
|
if(~got_first) begin
|
|
buf_rptr <= buf_wptr;
|
|
got_first <= 1;
|
|
end
|
|
else begin
|
|
ram_address <= buf_addr + buf_rptr;
|
|
ram_req <= ~ram_req;
|
|
buf_rptr <= buf_rptr + 1'd1;
|
|
len <= (buf_wptr < buf_rptr) ? (buf_len + buf_wptr - buf_rptr) : (buf_wptr - buf_rptr);
|
|
state <= 1;
|
|
end
|
|
end
|
|
else begin
|
|
len <= 0;
|
|
ce_cnt <= 0;
|
|
hurryup <= 0;
|
|
end
|
|
end
|
|
1: if(ram_ready) begin
|
|
ready <= 2;
|
|
readdata <= ram_data;
|
|
if(buf_rptr >= buf_len) buf_rptr <= buf_rptr - buf_len;
|
|
state <= 0;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
reg ce_sample;
|
|
always @(posedge clk) begin
|
|
reg [31:0] acc = 0;
|
|
|
|
ce_sample <= 0;
|
|
acc <= acc + 48000 + {hurryup,6'd0};
|
|
if(acc >= CLK_RATE) begin
|
|
acc <= acc - CLK_RATE;
|
|
ce_sample <= 1;
|
|
end
|
|
end
|
|
|
|
endmodule
|