From 169f38e7d1f081957a6613f8668df80ed6844c8f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 8 Aug 2018 15:41:00 +0200 Subject: [PATCH] ad_ip_jesd204_tpl_dac: Add support for modes with N or N' != 16 The ad_ip_jesd204_tpl_dac currently only supports JESD204 modes that have both N and N' set to 16. Newer DACs like the AD9172 support modes where N and N' are not equal to 16. Add support for these modes. The width of the internal channel data path is set to N, only processing as many bits as necessary. At the framer the data is up-sized to N' bits with tail bits inserted as necessary. This data is then passed to the link layer. The width at the DMA interface is kept at 16 bits per sample regardless of the configuration of either N or N'. This is done to keep the interface consistent with the existing infrastructure it will connect to like upack and DMA. The data is expected to the LSB aligned, the unused MSBs will be ignored. Same is true for the test-pattern data registers. These register keep their existing 16-bit layout, but unused MSBs will be ignored by the core. The PN generators are modified to create only N bits of data per sample. Note that while the core can now support modes with N' = 12 there is still the restriction that requires the number of frames per beat to be an even number. Which means that not all modes with N' = 12 can be supported yet. Signed-off-by: Lars-Peter Clausen --- library/axi_ad9144/axi_ad9144.v | 2 + library/axi_ad9152/axi_ad9152.v | 2 + .../ad_ip_jesd204_tpl_dac.v | 6 ++- .../ad_ip_jesd204_tpl_dac_channel.v | 29 +++++++---- .../ad_ip_jesd204_tpl_dac_core.v | 29 +++++++---- .../ad_ip_jesd204_tpl_dac_framer.v | 29 ++++++----- .../ad_ip_jesd204_tpl_dac_hw.tcl | 29 ++++++++--- .../ad_ip_jesd204_tpl_dac_ip.tcl | 4 ++ .../ad_ip_jesd204_tpl_dac_pn.v | 48 ++++++++++++------- 9 files changed, 125 insertions(+), 53 deletions(-) diff --git a/library/axi_ad9144/axi_ad9144.v b/library/axi_ad9144/axi_ad9144.v index e69544428..9c4ceaff9 100644 --- a/library/axi_ad9144/axi_ad9144.v +++ b/library/axi_ad9144/axi_ad9144.v @@ -132,6 +132,8 @@ module axi_ad9144 #( .ID (ID), .NUM_LANES (NUM_CHANNELS * 2), .NUM_CHANNELS (NUM_CHANNELS), + .CONVERTER_RESOLUTION (16), + .BITS_PER_SAMPLE (16), .SAMPLES_PER_FRAME (1), .DDS_TYPE (DAC_DDS_TYPE), .DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), diff --git a/library/axi_ad9152/axi_ad9152.v b/library/axi_ad9152/axi_ad9152.v index 4605111e9..702d13dc3 100644 --- a/library/axi_ad9152/axi_ad9152.v +++ b/library/axi_ad9152/axi_ad9152.v @@ -92,6 +92,8 @@ module axi_ad9152 #( .ID(ID), .NUM_LANES(4), .NUM_CHANNELS(2), + .CONVERTER_RESOLUTION (16), + .BITS_PER_SAMPLE (16), .SAMPLES_PER_FRAME (1), .DDS_TYPE (DAC_DDS_TYPE), .DDS_CORDIC_DW (DAC_DDS_CORDIC_DW), diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac.v b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac.v index c55574086..b211a4122 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac.v +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac.v @@ -28,6 +28,8 @@ module ad_ip_jesd204_tpl_dac #( parameter NUM_LANES = 4, parameter NUM_CHANNELS = 2, parameter SAMPLES_PER_FRAME = 1, + parameter CONVERTER_RESOLUTION = 16, + parameter BITS_PER_SAMPLE = 16, parameter DDS_TYPE = 1, parameter DDS_CORDIC_DW = 16, parameter DDS_CORDIC_PHASE_DW = 16, @@ -81,8 +83,9 @@ module ad_ip_jesd204_tpl_dac #( /* Static for now */ localparam OCTETS_PER_BEAT = 4; - localparam DATA_PATH_WIDTH = 2 * OCTETS_PER_BEAT * NUM_LANES / NUM_CHANNELS; + localparam DATA_PATH_WIDTH = OCTETS_PER_BEAT * 8 * NUM_LANES / NUM_CHANNELS / BITS_PER_SAMPLE; localparam LINK_DATA_WIDTH = NUM_LANES * OCTETS_PER_BEAT * 8; + localparam DMA_DATA_WIDTH = 16 * DATA_PATH_WIDTH * NUM_CHANNELS; // internal signals @@ -157,6 +160,7 @@ module ad_ip_jesd204_tpl_dac #( .OCTETS_PER_BEAT (OCTETS_PER_BEAT), .DATA_PATH_WIDTH (DATA_PATH_WIDTH), .LINK_DATA_WIDTH (LINK_DATA_WIDTH), + .DMA_DATA_WIDTH (DMA_DATA_WIDTH), .DDS_TYPE (DDS_TYPE), .DDS_CORDIC_DW (DDS_CORDIC_DW), .DDS_CORDIC_PHASE_DW (DDS_CORDIC_PHASE_DW) diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_channel.v b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_channel.v index b4d6f38b6..a8557111f 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_channel.v +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_channel.v @@ -26,6 +26,7 @@ module ad_ip_jesd204_tpl_dac_channel #( parameter DATAPATH_DISABLE = 0, parameter DATA_PATH_WIDTH = 4, + parameter CONVERTER_RESOLUTION = 16, parameter DDS_TYPE = 1, parameter DDS_CORDIC_DW = 16, parameter DDS_CORDIC_PHASE_DW = 16 @@ -35,12 +36,12 @@ module ad_ip_jesd204_tpl_dac_channel #( input clk, input [DATA_PATH_WIDTH*16-1:0] dma_data, - output reg [DATA_PATH_WIDTH*16-1:0] dac_data = 'h00, + output reg [DATA_PATH_WIDTH*CONVERTER_RESOLUTION-1:0] dac_data = 'h00, // PN data - input [DATA_PATH_WIDTH*16-1:0] pn7_data, - input [DATA_PATH_WIDTH*16-1:0] pn15_data, + input [DATA_PATH_WIDTH*CONVERTER_RESOLUTION-1:0] pn7_data, + input [DATA_PATH_WIDTH*CONVERTER_RESOLUTION-1:0] pn15_data, // Configuration @@ -62,14 +63,18 @@ module ad_ip_jesd204_tpl_dac_channel #( output reg dac_enable = 1'b0 ); + localparam CR = CONVERTER_RESOLUTION; + localparam CHANNEL_DATA_WIDTH = DATA_PATH_WIDTH * CR; + // internal signals - wire [DATA_PATH_WIDTH*16-1:0] dac_dds_data_s; - wire [DATA_PATH_WIDTH*16-1:0] dac_pat_data_s; + wire [CHANNEL_DATA_WIDTH-1:0] dac_dds_data_s; + wire [CHANNEL_DATA_WIDTH-1:0] dac_dma_data_s; + wire [CHANNEL_DATA_WIDTH-1:0] dac_pat_data_s; generate if (DATA_PATH_WIDTH > 1) begin - assign dac_pat_data_s = {DATA_PATH_WIDTH/2{dac_pat_data_1,dac_pat_data_0}}; + assign dac_pat_data_s = {DATA_PATH_WIDTH/2{dac_pat_data_1[0+:CR],dac_pat_data_0[0+:CR]}}; end else begin reg dac_pat_data_sel = 1'b0; @@ -82,7 +87,13 @@ module ad_ip_jesd204_tpl_dac_channel #( end assign dac_pat_data_s = dac_pat_data_sel == 1'b0 ? - dac_pat_data_0 : dac_pat_data_1; + dac_pat_data_0[0+:CR] : dac_pat_data_1[0+:CR]; + end + + genvar i; + /* Data is expected to be LSB aligned, drop unused MSBs */ + for (i = 0; i < DATA_PATH_WIDTH; i = i + 1) begin: g_dac_dma_data + assign dac_dma_data_s[CR*i+:CR] = dma_data[16*i+:CR]; end endgenerate @@ -96,7 +107,7 @@ module ad_ip_jesd204_tpl_dac_channel #( 4'h5: dac_data <= ~pn15_data; 4'h4: dac_data <= ~pn7_data; 4'h3: dac_data <= 'h00; - 4'h2: dac_data <= dma_data; + 4'h2: dac_data <= dac_dma_data_s; 4'h1: dac_data <= dac_pat_data_s; default: dac_data <= dac_dds_data_s; endcase @@ -106,7 +117,7 @@ module ad_ip_jesd204_tpl_dac_channel #( ad_dds #( .DISABLE (DATAPATH_DISABLE), - .DDS_DW (16), + .DDS_DW (CONVERTER_RESOLUTION), .PHASE_DW (16), .DDS_TYPE (DDS_TYPE), .CORDIC_DW (DDS_CORDIC_DW), diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_core.v b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_core.v index e890a3aa6..94e4534f8 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_core.v +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_core.v @@ -27,10 +27,13 @@ module ad_ip_jesd204_tpl_dac_core #( parameter DATAPATH_DISABLE = 0, parameter NUM_LANES = 1, parameter NUM_CHANNELS = 1, + parameter BITS_PER_SAMPLE = 16, + parameter CONVERTER_RESOLUTION = 16, parameter SAMPLES_PER_FRAME = 1, parameter OCTETS_PER_BEAT = 4, parameter DATA_PATH_WIDTH = 4, parameter LINK_DATA_WIDTH = NUM_LANES * OCTETS_PER_BEAT * 8, + parameter DMA_DATA_WIDTH = DATA_PATH_WIDTH * 16 * NUM_CHANNELS, parameter DDS_TYPE = 1, parameter DDS_CORDIC_DW = 16, parameter DDS_CORDIC_PHASE_DW = 16 @@ -44,7 +47,7 @@ module ad_ip_jesd204_tpl_dac_core #( // dma interface output [NUM_CHANNELS-1:0] dac_valid, - input [LINK_DATA_WIDTH-1:0] dac_ddata, + input [DMA_DATA_WIDTH-1:0] dac_ddata, // Configuration interface @@ -66,21 +69,28 @@ module ad_ip_jesd204_tpl_dac_core #( output [NUM_CHANNELS-1:0] enable ); + localparam DAC_CDW = CONVERTER_RESOLUTION * DATA_PATH_WIDTH; + localparam DAC_DATA_WIDTH = DAC_CDW * NUM_CHANNELS; + localparam DMA_CDW = DATA_PATH_WIDTH * 16; + assign link_valid = 1'b1; - wire [LINK_DATA_WIDTH-1:0] dac_data_s; + wire [DAC_DATA_WIDTH-1:0] dac_data_s; - wire [DATA_PATH_WIDTH*16-1:0] pn7_data; - wire [DATA_PATH_WIDTH*16-1:0] pn15_data; + wire [DAC_CDW-1:0] pn7_data; + wire [DAC_CDW-1:0] pn15_data; // device interface ad_ip_jesd204_tpl_dac_framer #( .NUM_LANES (NUM_LANES), .NUM_CHANNELS (NUM_CHANNELS), + .BITS_PER_SAMPLE (BITS_PER_SAMPLE), + .CONVERTER_RESOLUTION (CONVERTER_RESOLUTION), .SAMPLES_PER_FRAME (SAMPLES_PER_FRAME), .OCTETS_PER_BEAT (OCTETS_PER_BEAT), - .LINK_DATA_WIDTH (LINK_DATA_WIDTH) + .LINK_DATA_WIDTH (LINK_DATA_WIDTH), + .DAC_DATA_WIDTH (DAC_DATA_WIDTH) ) i_framer ( .link_data (link_data), .dac_data (dac_data_s) @@ -88,7 +98,8 @@ module ad_ip_jesd204_tpl_dac_core #( // PN generator ad_ip_jesd204_tpl_dac_pn #( - .DATA_PATH_WIDTH (DATA_PATH_WIDTH) + .DATA_PATH_WIDTH (DATA_PATH_WIDTH), + .CONVERTER_RESOLUTION (CONVERTER_RESOLUTION) ) i_pn_gen ( .clk (clk), .reset (dac_sync), @@ -101,13 +112,13 @@ module ad_ip_jesd204_tpl_dac_core #( assign dac_valid = {NUM_CHANNELS{1'b1}}; - localparam CDW = DATA_PATH_WIDTH * 16; generate genvar i; for (i = 0; i < NUM_CHANNELS; i = i + 1) begin: g_channel ad_ip_jesd204_tpl_dac_channel #( .DATA_PATH_WIDTH (DATA_PATH_WIDTH), + .CONVERTER_RESOLUTION (CONVERTER_RESOLUTION), .DATAPATH_DISABLE (DATAPATH_DISABLE), .DDS_TYPE (DDS_TYPE), .DDS_CORDIC_DW (DDS_CORDIC_DW), @@ -115,8 +126,8 @@ module ad_ip_jesd204_tpl_dac_core #( ) i_channel ( .clk (clk), .dac_enable (enable[i]), - .dac_data (dac_data_s[CDW*i+:CDW]), - .dma_data (dac_ddata[CDW*i+:CDW]), + .dac_data (dac_data_s[DAC_CDW*i+:DAC_CDW]), + .dma_data (dac_ddata[DMA_CDW*i+:DMA_CDW]), .pn7_data (pn7_data), .pn15_data (pn15_data), diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_framer.v b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_framer.v index e2becf7b8..b5dfa1307 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_framer.v +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_framer.v @@ -26,9 +26,12 @@ module ad_ip_jesd204_tpl_dac_framer #( parameter NUM_LANES = 8, parameter NUM_CHANNELS = 4, + parameter BITS_PER_SAMPLE = 16, + parameter CONVERTER_RESOLUTION = 16, parameter SAMPLES_PER_FRAME = 2, parameter OCTETS_PER_BEAT = 4, - parameter LINK_DATA_WIDTH = OCTETS_PER_BEAT * 8 * NUM_LANES + parameter LINK_DATA_WIDTH = OCTETS_PER_BEAT * 8 * NUM_LANES, + parameter DAC_DATA_WIDTH = LINK_DATA_WIDTH * CONVERTER_RESOLUTION / BITS_PER_SAMPLE ) ( // jesd interface @@ -36,7 +39,7 @@ module ad_ip_jesd204_tpl_dac_framer #( // dac interface - input [LINK_DATA_WIDTH-1:0] dac_data + input [DAC_DATA_WIDTH-1:0] dac_data ); /* @@ -44,7 +47,7 @@ module ad_ip_jesd204_tpl_dac_framer #( * JESD204 link expects for the specified framer configuration. * * The input sample data in dac_data is expected to be grouped by converter. - * The first sample is in the LSBs. + * The first sample is in the LSBs. Each sample has CONVERTER_RESOLUTION bits. * * Or in other words the data in dac_data is expected to have the following * layout. @@ -86,12 +89,12 @@ module ad_ip_jesd204_tpl_dac_framer #( * ordered in either case. That means lower bits are in the LSBs. */ - localparam BITS_PER_SAMPLE = 16; - localparam FRAMES_PER_BEAT = 8 * OCTETS_PER_BEAT / BITS_PER_LANE_PER_FRAME; - localparam SAMPLES_PER_BEAT = LINK_DATA_WIDTH / 16; + localparam FRAMES_PER_BEAT = OCTETS_PER_BEAT * 8 / BITS_PER_LANE_PER_FRAME; + localparam SAMPLES_PER_BEAT = DAC_DATA_WIDTH / CONVERTER_RESOLUTION; localparam BITS_PER_CHANNEL_PER_FRAME = BITS_PER_SAMPLE * SAMPLES_PER_FRAME; localparam BITS_PER_LANE_PER_FRAME = BITS_PER_CHANNEL_PER_FRAME * NUM_CHANNELS / NUM_LANES; + localparam TAIL_BITS = BITS_PER_SAMPLE - CONVERTER_RESOLUTION; wire [LINK_DATA_WIDTH-1:0] link_data_msb_s; wire [LINK_DATA_WIDTH-1:0] frame_data_s; @@ -100,13 +103,17 @@ module ad_ip_jesd204_tpl_dac_framer #( generate genvar i; genvar j; - /* Reorder samples MSB first */ + /* Reorder samples MSB first and insert tail bits */ for (i = 0; i < SAMPLES_PER_BEAT; i = i + 1) begin: g_dac_data_msb - localparam w = BITS_PER_SAMPLE; - localparam src_lsb = i * w; - localparam dst_msb = LINK_DATA_WIDTH - 1 - src_lsb; + localparam src_w = CONVERTER_RESOLUTION; + localparam dst_w = BITS_PER_SAMPLE; + localparam src_lsb = i * src_w; + localparam dst_msb = LINK_DATA_WIDTH - 1 - i * dst_w; - assign dac_data_msb[dst_msb-:w] = dac_data[src_lsb+:w]; + assign dac_data_msb[dst_msb-:src_w] = dac_data[src_lsb+:src_w]; + if (TAIL_BITS > 0) begin + assign dac_data_msb[dst_msb-src_w-:TAIL_BITS] = {TAIL_BITS{1'b0}}; + end end /* Slice channel and pack it into frames */ diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_hw.tcl b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_hw.tcl index da3be53b2..d87a3d490 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_hw.tcl +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_hw.tcl @@ -81,6 +81,20 @@ ad_ip_parameter NUM_CHANNELS INTEGER 1 true [list \ GROUP $group \ ] +ad_ip_parameter BITS_PER_SAMPLE INTEGER 16 false [list \ + DISPLAY_NAME "Bits per Sample (N')" \ + ALLOWED_RANGES {12 16} \ + UNITS bits \ + GROUP $group \ +] + +ad_ip_parameter CONVERTER_RESOLUTION INTEGER 16 true [list \ + DISPLAY_NAME "Converter Resolution (N)" \ + ALLOWED_RANGES {11 12 16} \ + UNITS bits \ + GROUP $group \ +] + ad_ip_parameter SAMPLES_PER_FRAME INTEGER 1 true [list \ DISPLAY_NAME "Samples per Frame (S)" \ DISPLAY_UNITS "samples" \ @@ -141,22 +155,25 @@ proc p_ad_ip_jesd204_tpl_dac_elab {} { # read core parameters - set m_num_of_lanes [get_parameter_value "NUM_LANES"] - set m_num_of_channels [get_parameter_value "NUM_CHANNELS"] - set channel_bus_width [expr 32*$m_num_of_lanes/$m_num_of_channels] + set L [get_parameter_value "NUM_LANES"] + set M [get_parameter_value "NUM_CHANNELS"] + set NP [get_parameter_value "BITS_PER_SAMPLE"] + + # The DMA interface is always 16-bits per sample, regardless of NP + set channel_bus_width [expr 16 * (32 * $L / ($M * $NP))] # link layer interface add_interface link_data avalon_streaming source - add_interface_port link_data link_data data output [expr 32*$m_num_of_lanes] + add_interface_port link_data link_data data output [expr 32 * $L] add_interface_port link_data link_valid valid output 1 add_interface_port link_data link_ready ready input 1 set_interface_property link_data associatedClock link_clk - set_interface_property link_data dataBitsPerSymbol [expr 32*$m_num_of_lanes] + set_interface_property link_data dataBitsPerSymbol [expr 32 * $L] # dma interface - for {set i 0} {$i < $m_num_of_channels} {incr i} { + for {set i 0} {$i < $M} {incr i} { add_interface dac_ch_$i conduit end add_interface_port dac_ch_$i dac_enable_$i enable output 1 set_port_property dac_enable_$i fragment_list [format "enable(%d:%d)" $i $i] diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_ip.tcl b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_ip.tcl index 50e99c68e..17e011623 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_ip.tcl +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_ip.tcl @@ -86,6 +86,8 @@ foreach p {DDS_CORDIC_DW DDS_CORDIC_PHASE_DW} { foreach {p v} { "NUM_LANES" "1 2 3 4 8" \ "NUM_CHANNELS" "1 2 4 6 8" \ + "BITS_PER_SAMPLE" "12 16" \ + "CONVERTER_RESOLUTION" "11 12 16" \ "SAMPLES_PER_FRAME" "1 2 3 4 6 8 12 16" \ } { \ set_property -dict [list \ @@ -113,6 +115,8 @@ set i 0 foreach {k v} { \ "NUM_LANES" "Number of Lanes (L)" \ "NUM_CHANNELS" "Number of Conveters (M)" \ + "BITS_PER_SAMPLE" "Bits per Sample (N')" \ + "CONVERTER_RESOLUTION" "Converter Resolution (N)" \ "SAMPLES_PER_FRAME" "Samples per Frame (S)" \ } { \ set p [ipgui::get_guiparamspec -name $k -component $cc] diff --git a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_pn.v b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_pn.v index 9ad5c32fd..1ea887c5f 100644 --- a/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_pn.v +++ b/library/jesd204/ad_ip_jesd204_tpl_dac/ad_ip_jesd204_tpl_dac_pn.v @@ -24,26 +24,33 @@ `timescale 1ns/100ps module ad_ip_jesd204_tpl_dac_pn #( - parameter DATA_PATH_WIDTH = 4 + parameter DATA_PATH_WIDTH = 4, + parameter CONVERTER_RESOLUTION = 16 ) ( input clk, input reset, - output [DATA_PATH_WIDTH*16-1:0] pn7_data, - output [DATA_PATH_WIDTH*16-1:0] pn15_data + output [DATA_PATH_WIDTH*CONVERTER_RESOLUTION-1:0] pn7_data, + output [DATA_PATH_WIDTH*CONVERTER_RESOLUTION-1:0] pn15_data ); - localparam DW = DATA_PATH_WIDTH * 16 - 1; + localparam CR = CONVERTER_RESOLUTION; + localparam DW = DATA_PATH_WIDTH * CR - 1; - reg [DW:0] pn7_state = {DW+1{1'b1}}; - reg [DW:0] pn15_state = {DW+1{1'b1}}; + /* We need at least enough bits to store the PN state */ + localparam PN7_W = DW > 6 ? DW : 6; + localparam PN15_W = DW > 14 ? DW : 14; + + reg [PN7_W:0] pn7_state = {PN7_W+1{1'b1}}; + reg [PN15_W:0] pn15_state = {PN15_W+1{1'b1}}; wire [DW:0] pn7; wire [DW+7:0] pn7_full_state; - wire [DW:0] pn7_reset; + wire [PN7_W:0] pn7_reset; + wire [DW:0] pn15; wire [DW+15:0] pn15_full_state; - wire [DW:0] pn15_reset; + wire [PN15_W:0] pn15_reset; /* PN7 x^7 + x^6 + 1 */ assign pn7 = pn7_full_state[7+:DW+1] ^ pn7_full_state[6+:DW+1]; @@ -53,19 +60,26 @@ module ad_ip_jesd204_tpl_dac_pn #( assign pn15 = pn15_full_state[15+:DW+1] ^ pn15_full_state[14+:DW+1]; assign pn15_full_state = {pn15_state[14:0],pn15}; - assign pn7_reset[DW-:7] = {7{1'b1}}; - assign pn7_reset[DW-7:0] = pn7_reset[DW:7] ^ pn7_reset[DW-1:6]; + assign pn7_reset[PN7_W-:7] = {7{1'b1}}; + assign pn15_reset[PN15_W-:15] = {15{1'b1}}; - assign pn15_reset[DW-:15] = {15{1'b1}}; - assign pn15_reset[DW-15:0] = pn15_reset[DW:15] ^ pn15_reset[DW-1:14]; + generate + if (PN7_W >= 7) begin + assign pn7_reset[PN7_W-7:0] = pn7_reset[PN7_W:7] ^ pn7_reset[PN7_W-1:6]; + end + + if (PN15_W >= 15) begin + assign pn15_reset[PN15_W-15:0] = pn15_reset[PN15_W:15] ^ pn15_reset[PN15_W-1:14]; + end + endgenerate always @(posedge clk) begin if (reset == 1'b1) begin pn7_state <= pn7_reset; pn15_state <= pn15_reset; end else begin - pn7_state <= pn7; - pn15_state <= pn15; + pn7_state <= pn7_full_state[PN7_W:0]; + pn15_state <= pn15_full_state[PN15_W:0]; end end @@ -76,9 +90,9 @@ module ad_ip_jesd204_tpl_dac_pn #( * sample of the PN state and put it into the LSB sample of the output data. */ genvar i; - for (i = 0; i <= DW; i = i + 16) begin: g_pn_swizzle - assign pn7_data[i+:16] = pn7_state[DW-i-:16]; - assign pn15_data[i+:16] = pn15_state[DW-i-:16]; + for (i = 0; i <= DW; i = i + CR) begin: g_pn_swizzle + assign pn7_data[i+:CR] = pn7_state[PN7_W-i-:CR]; + assign pn15_data[i+:CR] = pn15_state[PN15_W-i-:CR]; end endgenerate