From c354bb8cb80a6f945261617dbcd0808790753701 Mon Sep 17 00:00:00 2001 From: slederer Date: Fri, 26 Sep 2025 01:36:26 +0200 Subject: [PATCH] tdraudio: implement multiple channels --- tridoracpu/tridoracpu.srcs/tdraudio.v | 90 +++++++++++++++++++++------ tridoracpu/tridoracpu.srcs/top.v | 2 +- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/tridoracpu/tridoracpu.srcs/tdraudio.v b/tridoracpu/tridoracpu.srcs/tdraudio.v index ac87abf..6f41a6f 100644 --- a/tridoracpu/tridoracpu.srcs/tdraudio.v +++ b/tridoracpu/tridoracpu.srcs/tdraudio.v @@ -1,27 +1,23 @@ `timescale 1ns / 1ps -module tdraudio #(DATA_WIDTH=32) ( +// waveform generator module (only pulse wave for now) +module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22, AMP_WIDTH=16) ( input wire clk, input wire reset, - input wire [3:0] reg_sel, + input wire [1:0] reg_sel, output wire [DATA_WIDTH-1:0] rd_data, input wire [DATA_WIDTH-1:0] wr_data, input wire rd_en, input wire wr_en, - output wire pdm_out, - output wire gain_sel, - output wire shutdown_n + output wire [AMP_WIDTH-1:0] amp_val, + output wire running ); - localparam CLOCK_DIV_WIDTH = 22; - localparam AMP_WIDTH = 16; - localparam TDRAU_REG_CTL = 0; /* control register */ localparam TDRAU_REG_CLK = 1; /* clock divider register */ localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */ - wire audio_out; reg channel_enable; reg [CLOCK_DIV_WIDTH-1:0] clock_div; reg [CLOCK_DIV_WIDTH-1:0] div_count; @@ -29,12 +25,10 @@ module tdraudio #(DATA_WIDTH=32) ( reg [AMP_WIDTH-1:0] amp_start; reg [AMP_WIDTH-1:0] amp_out; - reg [AMP_WIDTH:0] deltasigma_acc; - - assign pdm_out = audio_out; - assign rd_data = {{DATA_WIDTH-8-CLOCK_DIV_WIDTH{1'b0}}, div_count, {7{1'b0}}, channel_enable}; - assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB - assign shutdown_n = channel_enable; + //assign rd_data = {{DATA_WIDTH-8-CLOCK_DIV_WIDTH{1'b0}}, div_count, {7{1'b0}}, channel_enable}; + assign rd_data = {8'b0, amp_start, {7{1'b0}}, channel_enable}; + assign amp_val = amp_out; + assign running = channel_enable; /* channel enable flag */ always @(posedge clk) @@ -101,6 +95,64 @@ module tdraudio #(DATA_WIDTH=32) ( // because div_count will become zero amp_phase <= 1; end +endmodule + +module tdraudio #(DATA_WIDTH=32) ( + input wire clk, + input wire reset, + input wire [6:0] io_addr, + output wire [DATA_WIDTH-1:0] rd_data, + input wire [DATA_WIDTH-1:0] wr_data, + input wire rd_en, + input wire wr_en, + + output wire pdm_out, + output wire gain_sel, + output wire shutdown_n + ); + + localparam CLOCK_DIV_WIDTH = 22; + localparam AMP_WIDTH = 16; + + wire chan_sel = io_addr[6:2]; + wire [1:0] reg_sel = io_addr[1:0]; + + wire [AMP_WIDTH-1:0] chan0_amp; + wire [DATA_WIDTH-1:0] chan0_rd_data; + wire chan0_running; + wire chan0_sel = chan_sel == 0; + wire chan0_rd_en = chan0_sel && rd_en; + wire chan0_wr_en = chan0_sel && wr_en; + + wire [AMP_WIDTH-1:0] chan1_amp; + wire [DATA_WIDTH-1:0] chan1_rd_data; + wire chan1_running; + wire chan1_sel = chan_sel == 1; + wire chan1_rd_en = chan1_sel && rd_en; + wire chan1_wr_en = chan1_sel && wr_en; + + wire running = chan0_running || chan1_running; + + assign rd_data = chan0_sel ? chan0_rd_data : + chan1_sel ? chan1_rd_data : + {DATA_WIDTH{1'b1}}; + + wavegen chan0(clk, reset, reg_sel, + chan0_rd_data, wr_data, + chan0_rd_en, chan0_wr_en, + chan0_amp, chan0_running); + + wavegen chan1(clk, reset, reg_sel, + chan1_rd_data, wr_data, + chan1_rd_en, chan1_wr_en, + chan1_amp, chan1_running); + + reg [AMP_WIDTH:0] deltasigma_acc; // one extra bit + wire [AMP_WIDTH:0] amp_sum = chan0_amp + chan1_amp; // also one overflow bit here + wire [AMP_WIDTH-1:0] amp_sum_scaled = amp_sum[AMP_WIDTH:1]; // shifted right to scale down + assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB + + assign shutdown_n = running; /* delta-sigma DAC */ always @(posedge clk) @@ -108,10 +160,10 @@ module tdraudio #(DATA_WIDTH=32) ( if(reset) deltasigma_acc <= 0; else - if (channel_enable) - deltasigma_acc <= deltasigma_acc[AMP_WIDTH-1:0] + amp_out; + if (running) + deltasigma_acc <= deltasigma_acc[AMP_WIDTH-1:0] + amp_sum_scaled; end /* 1-bit audio output */ - assign audio_out = deltasigma_acc[AMP_WIDTH]; -endmodule \ No newline at end of file + assign pdm_out = deltasigma_acc[AMP_WIDTH]; +endmodule diff --git a/tridoracpu/tridoracpu.srcs/top.v b/tridoracpu/tridoracpu.srcs/top.v index 81d236b..4d0135e 100644 --- a/tridoracpu/tridoracpu.srcs/top.v +++ b/tridoracpu/tridoracpu.srcs/top.v @@ -248,7 +248,7 @@ module top( assign tdraudio_wr_data = mem_write_data; tdraudio tdraudio0(`clock, ~rst, - mem_addr[3:0], + mem_addr[6:0], tdraudio_rd_data, tdraudio_wr_data, tdraudio_rd_en,