pluto_hdl_adi/library/util_dac_unpack/util_dac_unpack.v

225 lines
7.5 KiB
Verilog

// ***************************************************************************
// ***************************************************************************
// Copyright 2014(c) Analog Devices, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// - Neither the name of Analog Devices, Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
// - The use of this software may or may not infringe the patent rights
// of one or more patent holders. This license does not release you
// from the requirement that you obtain separate licenses from these
// patent holders to use this software.
// - Use of the software either in source or binary form, must be run
// on or directly connected to an Analog Devices Inc. component.
//
// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.
//
// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module util_dac_unpack (
clk,
dac_enable_00,
dac_valid_00,
dac_data_00,
dac_enable_01,
dac_valid_01,
dac_data_01,
dac_enable_02,
dac_valid_02,
dac_data_02,
dac_enable_03,
dac_valid_03,
dac_data_03,
dac_enable_04,
dac_valid_04,
dac_data_04,
dac_enable_05,
dac_valid_05,
dac_data_05,
dac_enable_06,
dac_valid_06,
dac_data_06,
dac_enable_07,
dac_valid_07,
dac_data_07,
fifo_valid,
dma_rd,
dma_data);
parameter CHANNELS = 8; // valid values are 4 and 8
parameter DATA_WIDTH = 16;
localparam DMA_WIDTH = CHANNELS * DATA_WIDTH;
input clk;
input dac_enable_00;
input dac_valid_00;
output [DATA_WIDTH-1:0] dac_data_00;
input dac_enable_01;
input dac_valid_01;
output [DATA_WIDTH-1:0] dac_data_01;
input dac_enable_02;
input dac_valid_02;
output [DATA_WIDTH-1:0] dac_data_02;
input dac_enable_03;
input dac_valid_03;
output [DATA_WIDTH-1:0] dac_data_03;
input dac_enable_04;
input dac_valid_04;
output [DATA_WIDTH-1:0] dac_data_04;
input dac_enable_05;
input dac_valid_05;
output [DATA_WIDTH-1:0] dac_data_05;
input dac_enable_06;
input dac_valid_06;
output [DATA_WIDTH-1:0] dac_data_06;
input dac_enable_07;
input dac_valid_07;
output [DATA_WIDTH-1:0] dac_data_07;
input fifo_valid;
output dma_rd;
input [DMA_WIDTH-1:0] dma_data;
wire [CHANNELS-1:0] dac_enable;
wire [CHANNELS-1:0] dac_valid;
wire [DATA_WIDTH-1:0] data_array[0:CHANNELS-1];
wire [$clog2(CHANNELS)-1:0] offset [0:CHANNELS-1];
wire dac_chan_valid;
reg [DATA_WIDTH*CHANNELS-1:0] dac_data = 'h00;
reg [DMA_WIDTH-1:0] buffer = 'h00;
reg dma_rd = 1'b0;
reg [$clog2(CHANNELS)-1:0] counter = 'h00;
reg [CHANNELS-1:0] dac_enable_d1 = 'h00;
assign dac_enable[0] = dac_enable_00;
assign dac_enable[1] = dac_enable_01;
assign dac_enable[2] = dac_enable_02;
assign dac_enable[3] = dac_enable_03;
assign dac_valid[0] = dac_valid_00;
assign dac_valid[1] = dac_valid_01;
assign dac_valid[2] = dac_valid_02;
assign dac_valid[3] = dac_valid_03;
assign dac_data_00 = dac_data[DATA_WIDTH*1-1:DATA_WIDTH*0];
assign dac_data_01 = dac_data[DATA_WIDTH*2-1:DATA_WIDTH*1];
assign dac_data_02 = dac_data[DATA_WIDTH*3-1:DATA_WIDTH*2];
assign dac_data_03 = dac_data[DATA_WIDTH*4-1:DATA_WIDTH*3];
generate
if (CHANNELS >= 8) begin
assign dac_enable[4] = dac_enable_04;
assign dac_enable[5] = dac_enable_05;
assign dac_enable[6] = dac_enable_06;
assign dac_enable[7] = dac_enable_07;
assign dac_valid[4] = dac_valid_04;
assign dac_valid[5] = dac_valid_05;
assign dac_valid[6] = dac_valid_06;
assign dac_valid[7] = dac_valid_07;
assign dac_data_04 = dac_data[DATA_WIDTH*5-1:DATA_WIDTH*4];
assign dac_data_05 = dac_data[DATA_WIDTH*6-1:DATA_WIDTH*5];
assign dac_data_06 = dac_data[DATA_WIDTH*7-1:DATA_WIDTH*6];
assign dac_data_07 = dac_data[DATA_WIDTH*8-1:DATA_WIDTH*7];
end
endgenerate
function integer enable_reduce;
input n;
integer n;
integer i;
begin
enable_reduce = 0;
for (i = 0; i < n; i = i + 1)
enable_reduce = enable_reduce + dac_enable[i];
end
endfunction
assign dac_chan_valid = |dac_valid;
always @(posedge clk) begin
if (fifo_valid == 1'b1) begin
buffer <= dma_data;
end
end
always @(posedge clk) begin
dma_rd <= 1'b0;
if (dac_enable != dac_enable_d1) begin
counter <= 'h00;
end else if (dac_chan_valid == 1'b1) begin
counter <= counter + enable_reduce(CHANNELS);
if (counter == 'h00)
dma_rd <= 1'b1;
end
dac_enable_d1 <= dac_enable;
end
generate
genvar i;
for (i = 0; i < CHANNELS; i = i + 1) begin : gen_data_array
assign data_array[i] = buffer[DATA_WIDTH+i*DATA_WIDTH-1:i*DATA_WIDTH];
end
endgenerate
generate
genvar j;
for (j = 0; j < CHANNELS; j = j + 1) begin : gen_dac_data
assign offset[j] = counter + enable_reduce(j);
always @(posedge clk) begin
if (dac_enable[j])
dac_data[DATA_WIDTH+j*DATA_WIDTH-1:j*DATA_WIDTH] <= data_array[offset[j]];
else
dac_data[DATA_WIDTH+j*DATA_WIDTH-1:j*DATA_WIDTH] <= 'h0000;
end
end
endgenerate
endmodule
// ***************************************************************************
// ***************************************************************************