From ad7e95b169f607b9c214eef1d0f26f6f28c95145 Mon Sep 17 00:00:00 2001 From: AndreiGrozav Date: Tue, 3 Apr 2018 15:38:17 +0300 Subject: [PATCH] ad_dds: Add selectable out data width and fair rounding The CORDIC has a selectable width range for phase and data of 8-24. Regarding the width of phase and data, the wider they are the smaller the precision loss when shifting but with the cost of more FPGA utilization. The user must decide between precision and utilization. The DDS_WD parameter is independent of CORDIC(CORDIC_DW) or Polynomial(16bit), letting the user chose the output width. Here we encounter two scenarios: * DDS_DW < DDS data width - in this case, a fair rounding will be implemented corresponding to the truncated bits * DDS_DW > DDS data width - DDS out data left shift to get the corresponding concatenation bits. --- library/common/ad_dds.v | 76 +++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/library/common/ad_dds.v b/library/common/ad_dds.v index e4a029129..1676c4662 100644 --- a/library/common/ad_dds.v +++ b/library/common/ad_dds.v @@ -37,51 +37,83 @@ module ad_dds #( - // data path disable - + // Disable DDS parameter DISABLE = 0, + // Range = 8-24 + parameter DDS_DW = 16, + // Set 1 for CORDIC or 2 for Polynomial parameter DDS_TYPE = 1, + // Range = 8-24 parameter CORDIC_DW = 16, + // Range = 8-24 ( make sure CORDIC_PHASE_DW < CORDIC_DW) parameter CORDIC_PHASE_DW = 16) ( // interface - input clk, - input dds_format, - input [15:0] dds_phase_0, - input [15:0] dds_scale_0, - input [15:0] dds_phase_1, - input [15:0] dds_scale_1, - output [15:0] dds_data); + input clk, + input dds_format, + input [ 15:0] dds_phase_0, + input [ 15:0] dds_scale_0, + input [ 15:0] dds_phase_1, + input [ 15:0] dds_scale_1, + output [DDS_DW-1:0] dds_data); + + // Local parameters + + localparam CORDIC = 1; + localparam POLYNOMIAL = 2; + + // The width for Polynomial DDS is fixed (16) + localparam DDS_D_DW = (DDS_TYPE == CORDIC) ? CORDIC_DW : 16; + localparam DDS_P_DW = (DDS_TYPE == CORDIC) ? CORDIC_PHASE_DW : 16; + // concatenation or truncation width + localparam C_T_WIDTH = (DDS_D_DW > DDS_DW) ? (DDS_D_DW - DDS_DW) : (DDS_DW - DDS_D_DW); // internal registers - reg [15:0] dds_data_int = 'd0; - reg [15:0] dds_data_out = 'd0; - reg [15:0] dds_scale_0_d = 'd0; - reg [15:0] dds_scale_1_d = 'd0; + reg [ DDS_DW-1:0] dds_data_width = 0; + reg [DDS_D_DW-1:0] dds_data_rownd = 0; + reg [DDS_D_DW-1:0] dds_data_int = 0; + reg [ 15:0] dds_scale_0_d = 0; + reg [ 15:0] dds_scale_1_d = 0; + reg [ DDS_DW-1:0] dds_data_out = 0; // internal signals wire [15:0] dds_data_0_s; wire [15:0] dds_data_1_s; - // disable - + // disable DDS generate if (DISABLE == 1) begin - assign dds_data = 16'd0; + // assign 0 for the exact buss width to avoid warnings + assign dds_data = {DDS_DW{1'b0}}; end else begin + // dds channel output assign dds_data = dds_data_out; - // dds channel output + // output data format + always @(posedge clk) begin + dds_data_out[DDS_DW-1] <= dds_data_width[DDS_DW-1] ^ dds_format; + dds_data_out[DDS_DW-2: 0] <= dds_data_width[DDS_DW-2: 0]; + end - always @(posedge clk) begin - dds_data_int <= dds_data_0_s + dds_data_1_s; - dds_data_out[15:15] <= dds_data_int[15] ^ dds_format; - dds_data_out[14: 0] <= dds_data_int[14:0]; - end + // set desired data width + always @(posedge clk) begin + if (DDS_DW <= DDS_D_DW) begin // truncation + // fair rownding + dds_data_rownd <= dds_data_int + {(C_T_WIDTH){dds_data_int[DDS_D_DW-1]}}; + dds_data_width <= dds_data_rownd[DDS_D_DW-1:DDS_D_DW-DDS_DW]; + end else begin // concatenation + dds_data_width <= dds_data_int << C_T_WIDTH; + end + end + + // dual tone + always @(posedge clk) begin + dds_data_int <= dds_data_0_s + dds_data_1_s; + end always @(posedge clk) begin dds_scale_0_d <= dds_scale_0;