|
`timescale 1ns / 1ps
|
|
|
|
// This module is a third order delta/sigma modulator
|
|
// It uses no multiply only shifts by 1, 2 or 13
|
|
// There are only 7 adders used, it takes around 110 LUTs
|
|
module hq_dac
|
|
(
|
|
input reset,
|
|
input clk,
|
|
input clk_ena,
|
|
input [19:0] pcm_in,
|
|
output reg dac_out
|
|
);
|
|
|
|
// ======================================
|
|
// ============== Stage #1 ==============
|
|
// ======================================
|
|
wire [23:0] w_data_in_p0;
|
|
wire [23:0] w_data_err_p0;
|
|
wire [23:0] w_data_int_p0;
|
|
reg [23:0] r_data_fwd_p1;
|
|
|
|
// PCM input extended to 24 bits
|
|
assign w_data_in_p0 = { {4{pcm_in[19]}}, pcm_in };
|
|
|
|
// Error between the input and the quantizer output
|
|
assign w_data_err_p0 = w_data_in_p0 - w_data_qt_p2;
|
|
|
|
// First integrator adder
|
|
assign w_data_int_p0 = { {3{w_data_err_p0[23]}}, w_data_err_p0[22:2] } // Divide by 4
|
|
+ r_data_fwd_p1;
|
|
|
|
// First integrator forward delay
|
|
always @(posedge reset or posedge clk)
|
|
if (reset)
|
|
r_data_fwd_p1 <= 24'd0;
|
|
else if (clk_ena)
|
|
r_data_fwd_p1 <= w_data_int_p0;
|
|
|
|
// ======================================
|
|
// ============== Stage #2 ==============
|
|
// ======================================
|
|
wire [23:0] w_data_fb1_p1;
|
|
wire [23:0] w_data_fb2_p1;
|
|
wire [23:0] w_data_lpf_p1;
|
|
reg [23:0] r_data_lpf_p2;
|
|
|
|
// Feedback from the quantizer output
|
|
assign w_data_fb1_p1 = { {3{r_data_fwd_p1[23]}}, r_data_fwd_p1[22:2] } // Divide by 4
|
|
- { {3{w_data_qt_p2[23]}}, w_data_qt_p2[22:2] }; // Divide by 4
|
|
|
|
// Feedback from the third stage
|
|
assign w_data_fb2_p1 = w_data_fb1_p1
|
|
- { {14{r_data_fwd_p2[23]}}, r_data_fwd_p2[22:13] }; // Divide by 8192
|
|
|
|
// Low pass filter
|
|
assign w_data_lpf_p1 = w_data_fb2_p1 + r_data_lpf_p2;
|
|
|
|
// Low pass filter feedback delay
|
|
always @(posedge reset or posedge clk)
|
|
if (reset)
|
|
r_data_lpf_p2 <= 24'd0;
|
|
else if (clk_ena)
|
|
r_data_lpf_p2 <= w_data_lpf_p1;
|
|
|
|
// ======================================
|
|
// ============== Stage #3 ==============
|
|
// ======================================
|
|
wire [23:0] w_data_fb3_p1;
|
|
wire [23:0] w_data_int_p1;
|
|
reg [23:0] r_data_fwd_p2;
|
|
|
|
// Feedback from the quantizer output
|
|
assign w_data_fb3_p1 = { {2{w_data_lpf_p1[23]}}, w_data_lpf_p1[22:1] } // Divide by 2
|
|
- { {2{w_data_qt_p2[23]}}, w_data_qt_p2[22:1] }; // Divide by 2
|
|
|
|
// Second integrator adder
|
|
assign w_data_int_p1 = w_data_fb3_p1 + r_data_fwd_p2;
|
|
|
|
// Second integrator forward delay
|
|
always @(posedge reset or posedge clk)
|
|
if (reset)
|
|
r_data_fwd_p2 <= 24'd0;
|
|
else if (clk_ena)
|
|
r_data_fwd_p2 <= w_data_int_p1;
|
|
|
|
// =====================================
|
|
// ========== 1-bit quantizer ==========
|
|
// =====================================
|
|
wire [23:0] w_data_qt_p2;
|
|
|
|
assign w_data_qt_p2 = (r_data_fwd_p2[23]) ? 24'hF00000 : 24'h100000;
|
|
|
|
always @(posedge reset or posedge clk)
|
|
if (reset)
|
|
dac_out <= 1'b0;
|
|
else if (clk_ena)
|
|
dac_out <= ~r_data_fwd_p2[23];
|
|
|
|
endmodule
|