MacPlus_MiSTer/sys/alsa.sv

158 lines
3.7 KiB
Systemverilog
Raw Normal View History

2019-03-08 21:31:23 +00:00
//============================================================================
//
// ALSA sound support for MiSTer
2020-01-21 16:55:46 +00:00
// (c)2019,2020 Alexey Melnikov
2019-03-08 21:31:23 +00:00
//
// 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
2021-01-23 12:09:42 +00:00
#(
parameter CLK_RATE = 24576000
)
2019-03-08 21:31:23 +00:00
(
input reset,
2020-01-21 16:55:46 +00:00
input clk,
output reg [31:3] ram_address,
input [63:0] ram_data,
output reg ram_req = 0,
input ram_ready,
2019-07-11 22:22:16 +00:00
2019-03-08 21:31:23 +00:00
input spi_ss,
input spi_sck,
input spi_mosi,
2020-01-21 16:55:46 +00:00
output spi_miso,
2019-07-11 22:22:16 +00:00
2019-03-08 21:31:23 +00:00
output reg [15:0] pcm_l,
output reg [15:0] pcm_r
);
2020-01-21 16:55:46 +00:00
reg [60:0] buf_info;
reg [6:0] spicnt = 0;
2019-03-08 21:31:23 +00:00
always @(posedge spi_sck, posedge spi_ss) begin
2020-01-21 16:55:46 +00:00
reg [95:0] spi_data;
2019-07-11 22:22:16 +00:00
2019-03-08 21:31:23 +00:00
if(spi_ss) spicnt <= 0;
else begin
2020-01-21 16:55:46 +00:00
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]};
2019-03-08 21:31:23 +00:00
spicnt <= spicnt + 1'd1;
end
end
2020-01-21 16:55:46 +00:00
assign spi_miso = spi_out[{spicnt[4:3],~spicnt[2:0]}];
2019-03-08 21:31:23 +00:00
2020-01-21 16:55:46 +00:00
reg [31:0] spi_out = 0;
always @(posedge clk) if(spi_ss) spi_out <= {buf_rptr, hurryup, 8'h00};
2019-03-08 21:31:23 +00:00
2019-07-11 22:22:16 +00:00
2020-01-21 16:55:46 +00:00
reg [31:3] buf_addr;
reg [18:3] buf_len;
reg [18:3] buf_wptr = 0;
2019-07-11 22:22:16 +00:00
2020-01-21 16:55:46 +00:00
always @(posedge clk) begin
reg [60:0] data1,data2;
2019-03-08 21:31:23 +00:00
2020-01-21 16:55:46 +00:00
data1 <= buf_info;
data2 <= data1;
if(data2 == data1) {buf_wptr,buf_len,buf_addr} <= data2;
end
2019-03-08 21:31:23 +00:00
2020-01-21 16:55:46 +00:00
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;
2019-03-08 21:31:23 +00:00
end
2020-01-21 16:55:46 +00:00
else begin
2019-03-08 21:31:23 +00:00
2020-01-21 16:55:46 +00:00
//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
2019-03-08 21:31:23 +00:00
end
end
2020-01-21 16:55:46 +00:00
reg ce_sample;
always @(posedge clk) begin
reg [31:0] acc = 0;
2019-03-08 21:31:23 +00:00
2020-01-21 16:55:46 +00:00
ce_sample <= 0;
2021-01-23 12:09:42 +00:00
acc <= acc + 48000 + {hurryup,6'd0};
if(acc >= CLK_RATE) begin
acc <= acc - CLK_RATE;
2020-01-21 16:55:46 +00:00
ce_sample <= 1;
2019-03-08 21:31:23 +00:00
end
end
endmodule