ad_ip_jesd204_tpl_dac: Share PN sequence generator between all channels

All channels have a copy of the same logic to generate the PN sequences.

Sharing the PN sequence generator among all channels slightly reduces the
resource utilization of the core.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
main
Lars-Peter Clausen 2018-08-03 08:39:15 +02:00 committed by Lars-Peter Clausen
parent 0be4a5c10e
commit 5d044b9fd3
6 changed files with 115 additions and 58 deletions

View File

@ -22,6 +22,7 @@ GENERIC_DEPS += ad_ip_jesd204_tpl_dac.v
GENERIC_DEPS += ad_ip_jesd204_tpl_dac_channel.v GENERIC_DEPS += ad_ip_jesd204_tpl_dac_channel.v
GENERIC_DEPS += ad_ip_jesd204_tpl_dac_core.v GENERIC_DEPS += ad_ip_jesd204_tpl_dac_core.v
GENERIC_DEPS += ad_ip_jesd204_tpl_dac_framer.v GENERIC_DEPS += ad_ip_jesd204_tpl_dac_framer.v
GENERIC_DEPS += ad_ip_jesd204_tpl_dac_pn.v
GENERIC_DEPS += ad_ip_jesd204_tpl_dac_regmap.v GENERIC_DEPS += ad_ip_jesd204_tpl_dac_regmap.v
XILINX_DEPS += ../../xilinx/common/ad_mul.v XILINX_DEPS += ../../xilinx/common/ad_mul.v

View File

@ -37,6 +37,11 @@ module ad_ip_jesd204_tpl_dac_channel #(
input [DATA_PATH_WIDTH*16-1:0] dma_data, 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*16-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,
// Configuration // Configuration
input dac_data_sync, input dac_data_sync,
@ -57,60 +62,19 @@ module ad_ip_jesd204_tpl_dac_channel #(
output reg dac_enable = 1'b0 output reg dac_enable = 1'b0
); );
localparam DW = DATA_PATH_WIDTH * 16 - 1;
// internal registers
reg [DW:0] dac_pn7_data = 'd0;
reg [DW:0] dac_pn15_data = 'd0;
// internal signals // internal signals
wire [DW:0] dac_dds_data_s; wire [DATA_PATH_WIDTH*16-1:0] dac_dds_data_s;
wire [DW:0] pn15;
wire [DW+15:0] pn15_full_state;
wire [DW:0] dac_pn15_data_s;
wire [DW:0] pn15_reset;
wire [DW:0] pn7;
wire [DW+7:0] pn7_full_state;
wire [DW:0] dac_pn7_data_s;
wire [DW:0] pn7_reset;
// PN15 x^15 + x^14 + 1
assign pn15 = pn15_full_state[15+:DW+1] ^ pn15_full_state[14+:DW+1];
assign pn15_full_state = {dac_pn15_data[14:0],pn15};
assign pn15_reset[DW-:15] = {15{1'b1}};
assign pn15_reset[DW-15:0] = pn15_reset[DW:15] ^ pn15_reset[DW-1:14];
// PN7 x^7 + x^6 + 1
assign pn7 = pn7_full_state[7+:DW+1] ^ pn7_full_state[6+:DW+1];
assign pn7_full_state = {dac_pn7_data[6:0],pn7};
assign pn7_reset[DW-:7] = {7{1'b1}};
assign pn7_reset[DW-7:0] = pn7_reset[DW:7] ^ pn7_reset[DW-1:6];
generate
genvar i;
for (i = 0; i < DATA_PATH_WIDTH; i = i + 1) begin: g_pn_swizzle
localparam src_lsb = i * 16;
localparam dst_lsb = (DATA_PATH_WIDTH - i - 1) * 16;
assign dac_pn15_data_s[dst_lsb+:16] = dac_pn15_data[src_lsb+:16];
assign dac_pn7_data_s[dst_lsb+:16] = dac_pn7_data[src_lsb+:16];
end
endgenerate
// dac data select // dac data select
always @(posedge clk) begin always @(posedge clk) begin
dac_enable <= (dac_data_sel == 4'h2) ? 1'b1 : 1'b0; dac_enable <= (dac_data_sel == 4'h2) ? 1'b1 : 1'b0;
case (dac_data_sel) case (dac_data_sel)
4'h7: dac_data <= dac_pn15_data_s; 4'h7: dac_data <= pn15_data;
4'h6: dac_data <= dac_pn7_data_s; 4'h6: dac_data <= pn7_data;
4'h5: dac_data <= ~dac_pn15_data_s; 4'h5: dac_data <= ~pn15_data;
4'h4: dac_data <= ~dac_pn7_data_s; 4'h4: dac_data <= ~pn7_data;
4'h3: dac_data <= 'h00; 4'h3: dac_data <= 'h00;
4'h2: dac_data <= dma_data; 4'h2: dac_data <= dma_data;
4'h1: dac_data <= {DATA_PATH_WIDTH/2{dac_pat_data_1, dac_pat_data_0}}; 4'h1: dac_data <= {DATA_PATH_WIDTH/2{dac_pat_data_1, dac_pat_data_0}};
@ -118,18 +82,6 @@ module ad_ip_jesd204_tpl_dac_channel #(
endcase endcase
end end
// pn registers
always @(posedge clk) begin
if (dac_data_sync == 1'b1) begin
dac_pn15_data <= pn15_reset;
dac_pn7_data <= pn7_reset;
end else begin
dac_pn15_data <= pn15;
dac_pn7_data <= pn7;
end
end
// dds // dds
ad_dds #( ad_dds #(

View File

@ -67,6 +67,9 @@ module ad_ip_jesd204_tpl_dac_core #(
wire [NUM_LANES*32-1:0] dac_data_s; wire [NUM_LANES*32-1:0] dac_data_s;
wire [DATA_PATH_WIDTH*16-1:0] pn7_data;
wire [DATA_PATH_WIDTH*16-1:0] pn15_data;
// device interface // device interface
ad_ip_jesd204_tpl_dac_framer #( ad_ip_jesd204_tpl_dac_framer #(
@ -78,6 +81,17 @@ module ad_ip_jesd204_tpl_dac_core #(
.dac_data (dac_data_s) .dac_data (dac_data_s)
); );
// PN generator
ad_ip_jesd204_tpl_dac_pn #(
.DATA_PATH_WIDTH (DATA_PATH_WIDTH)
) i_pn_gen (
.clk (clk),
.reset (dac_sync),
.pn7_data (pn7_data),
.pn15_data (pn15_data)
);
// dac valid // dac valid
assign dac_valid = {NUM_CHANNELS{1'b1}}; assign dac_valid = {NUM_CHANNELS{1'b1}};
@ -99,6 +113,9 @@ module ad_ip_jesd204_tpl_dac_core #(
.dac_data (dac_data_s[CDW*i+:CDW]), .dac_data (dac_data_s[CDW*i+:CDW]),
.dma_data (dac_ddata[CDW*i+:CDW]), .dma_data (dac_ddata[CDW*i+:CDW]),
.pn7_data (pn7_data),
.pn15_data (pn15_data),
.dac_data_sync (dac_sync), .dac_data_sync (dac_sync),
.dac_dds_format (dac_dds_format), .dac_dds_format (dac_dds_format),

View File

@ -51,6 +51,7 @@ ad_ip_files ad_ip_jesd204_tpl_dac [list \
ad_ip_jesd204_tpl_dac_channel.v \ ad_ip_jesd204_tpl_dac_channel.v \
ad_ip_jesd204_tpl_dac_core.v \ ad_ip_jesd204_tpl_dac_core.v \
ad_ip_jesd204_tpl_dac_framer.v \ ad_ip_jesd204_tpl_dac_framer.v \
ad_ip_jesd204_tpl_dac_pn.v \
ad_ip_jesd204_tpl_dac_regmap.v \ ad_ip_jesd204_tpl_dac_regmap.v \
] ]

View File

@ -48,6 +48,7 @@ adi_ip_files ad_ip_jesd204_tpl_dac [list \
"ad_ip_jesd204_tpl_dac_core.v" \ "ad_ip_jesd204_tpl_dac_core.v" \
"ad_ip_jesd204_tpl_dac_framer.v" \ "ad_ip_jesd204_tpl_dac_framer.v" \
"ad_ip_jesd204_tpl_dac_regmap.v" \ "ad_ip_jesd204_tpl_dac_regmap.v" \
"ad_ip_jesd204_tpl_dac_pn.v" \
"ad_ip_jesd204_tpl_dac.v" ] "ad_ip_jesd204_tpl_dac.v" ]
adi_ip_properties ad_ip_jesd204_tpl_dac adi_ip_properties ad_ip_jesd204_tpl_dac

View File

@ -0,0 +1,85 @@
// ***************************************************************************
// ***************************************************************************
// Copyright 2018 (c) Analog Devices, Inc. All rights reserved.
//
// Each core or library found in this collection may have its own licensing terms.
// The user should keep this in in mind while exploring these cores.
//
// Redistribution and use in source and binary forms,
// with or without modification of this file, are permitted under the terms of either
// (at the option of the user):
//
// 1. The GNU General Public License version 2 as published by the
// Free Software Foundation, which can be found in the top level directory, or at:
// https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
//
// OR
//
// 2. An ADI specific BSD license as noted in the top level directory, or on-line at:
// https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE
//
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module ad_ip_jesd204_tpl_dac_pn #(
parameter DATA_PATH_WIDTH = 4
) (
input clk,
input reset,
output [DATA_PATH_WIDTH*16-1:0] pn7_data,
output [DATA_PATH_WIDTH*16-1:0] pn15_data
);
localparam DW = DATA_PATH_WIDTH * 16 - 1;
reg [DW:0] pn7_state = {DW+1{1'b1}};
reg [DW:0] pn15_state = {DW+1{1'b1}};
wire [DW:0] pn7;
wire [DW+7:0] pn7_full_state;
wire [DW:0] pn7_reset;
wire [DW:0] pn15;
wire [DW+15:0] pn15_full_state;
wire [DW:0] pn15_reset;
/* PN7 x^7 + x^6 + 1 */
assign pn7 = pn7_full_state[7+:DW+1] ^ pn7_full_state[6+:DW+1];
assign pn7_full_state = {pn7_state[6:0],pn7};
/* PN15 x^15 + x^14 + 1 */
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 pn15_reset[DW-:15] = {15{1'b1}};
assign pn15_reset[DW-15:0] = pn15_reset[DW:15] ^ pn15_reset[DW-1:14];
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;
end
end
generate
/*
* The first sample contains the first MSB of the PN sequence, but the first
* sample is also in the LSB of the output data. So extract data at the MSB
* 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];
end
endgenerate
endmodule