diff --git a/library/axi_dmac/Makefile b/library/axi_dmac/Makefile index 7cc298a46..7ed938bf3 100644 --- a/library/axi_dmac/Makefile +++ b/library/axi_dmac/Makefile @@ -5,13 +5,17 @@ LIBRARY_NAME := axi_dmac +GENERIC_DEPS += ../common/ad_mem.v GENERIC_DEPS += ../common/up_axi.v GENERIC_DEPS += 2d_transfer.v GENERIC_DEPS += address_generator.v GENERIC_DEPS += axi_dmac.v +GENERIC_DEPS += axi_dmac_burst_memory.v GENERIC_DEPS += axi_dmac_regmap.v GENERIC_DEPS += axi_dmac_regmap_request.v GENERIC_DEPS += axi_dmac_reset_manager.v +GENERIC_DEPS += axi_dmac_resize_dest.v +GENERIC_DEPS += axi_dmac_resize_src.v GENERIC_DEPS += axi_dmac_transfer.v GENERIC_DEPS += axi_register_slice.v GENERIC_DEPS += data_mover.v @@ -39,17 +43,10 @@ XILINX_DEPS += ../interfaces/fifo_wr.xml XILINX_DEPS += ../interfaces/fifo_wr_rtl.xml XILINX_LIB_DEPS += util_axis_fifo -XILINX_LIB_DEPS += util_axis_resize XILINX_LIB_DEPS += util_cdc -ALTERA_DEPS += ../common/ad_mem.v -ALTERA_DEPS += ../util_axis_fifo/address_gray.v -ALTERA_DEPS += ../util_axis_fifo/address_gray_pipelined.v -ALTERA_DEPS += ../util_axis_fifo/address_sync.v ALTERA_DEPS += ../util_axis_fifo/util_axis_fifo.v -ALTERA_DEPS += ../util_axis_resize/util_axis_resize.v ALTERA_DEPS += ../util_cdc/sync_bits.v -ALTERA_DEPS += ../util_cdc/sync_gray.v ALTERA_DEPS += axi_dmac_constr.sdc ALTERA_DEPS += axi_dmac_hw.tcl diff --git a/library/axi_dmac/axi_dmac_burst_memory.v b/library/axi_dmac/axi_dmac_burst_memory.v new file mode 100644 index 000000000..9ec373f2f --- /dev/null +++ b/library/axi_dmac/axi_dmac_burst_memory.v @@ -0,0 +1,341 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +module axi_dmac_burst_memory #( + parameter DATA_WIDTH_SRC = 64, + parameter DATA_WIDTH_DEST = 64, + parameter ID_WIDTH = 3, + parameter MAX_BYTES_PER_BURST = 128, + parameter ASYNC_CLK = 1 +) ( + input src_clk, + input src_reset, + + input src_data_valid, + output src_data_ready, + input [DATA_WIDTH_SRC-1:0] src_data, + input src_data_last, + + input dest_clk, + input dest_reset, + + output dest_data_valid, + input dest_data_ready, + output [DATA_WIDTH_DEST-1:0] dest_data +); + +localparam DATA_WIDTH = DATA_WIDTH_SRC > DATA_WIDTH_DEST ? + DATA_WIDTH_SRC : DATA_WIDTH_DEST; + +/* A burst can have up to 256 beats */ +localparam BURST_LEN = MAX_BYTES_PER_BURST / (DATA_WIDTH / 8); +localparam BURST_LEN_WIDTH = BURST_LEN > 128 ? 8 : + BURST_LEN > 64 ? 7 : + BURST_LEN > 32 ? 6 : + BURST_LEN > 16 ? 5 : + BURST_LEN > 8 ? 4 : + BURST_LEN > 4 ? 3 : + BURST_LEN > 2 ? 2 : 1; + +localparam ADDRESS_WIDTH = BURST_LEN_WIDTH + ID_WIDTH - 1; + +localparam AUX_FIFO_SIZE = 2**(ID_WIDTH-1); + +/* + * The burst memory is separated into 2**(ID_WIDTH-1) segments. Each segment can + * hold up to BURST_LEN beats. The addresses that are used to access the memory + * are split into two parts. The MSBs index the segment and the LSBs index a + * beat in a specific segment. + * + * src_id and dest_id are used to index the segment of the burst memory on the + * write and read side respectively. The IDs are 1 bit wider than the address of + * the burst memory. So we can't use them directly as an index into the burst + * memory. Since the IDs are gray counted we also can't just leave out the MSB + * like with a binary counter. But XOR-ing the two MSBs of a gray counter gives + * us a gray counter of 1 bit less. Use this to generate the segment index. + * These addresses are captured in the src_id_reduced and dest_id_reduced + * signals. + * + * src_beat_counter and dest_beat_counter are used to index the beat on the + * write and read side respectively. They will be incremented for each beat that + * is written/read. Note that the beat counters are not reset to 0 on the last + * beat of a burst. This means the first beat of a burst might not be stored at + * offset 0 in the segment memory. But this is OK since the beat counter + * increments modulo the segment size and both the write and read side agree on + * the order. + */ + +reg [ID_WIDTH-1:0] src_id_next; +reg [ID_WIDTH-1:0] src_id = 'h0; +reg src_id_reduced_msb = 1'b0; +reg [BURST_LEN_WIDTH-1:0] src_beat_counter = 'h00; +reg src_mem_data_ready = 1'b0; + +reg [ID_WIDTH-1:0] dest_id_next = 'h0; +reg dest_id_reduced_msb_next = 1'b0; +reg dest_id_reduced_msb = 1'b0; +reg [ID_WIDTH-1:0] dest_id = 'h0; +reg [BURST_LEN_WIDTH-1:0] dest_beat_counter = 'h00; +reg [BURST_LEN_WIDTH-1:0] dest_burst_len = 'h00; +reg dest_valid = 1'b0; +reg dest_mem_data_valid = 1'b0; +reg dest_mem_data_last = 1'b0; + +reg [BURST_LEN_WIDTH-1:0] burst_len_mem[0:AUX_FIFO_SIZE-1]; + +wire src_beat; +wire src_last_beat; +wire [ID_WIDTH-1:0] src_dest_id; +wire [ADDRESS_WIDTH-1:0] src_waddr; +wire [ID_WIDTH-2:0] src_id_reduced; +wire src_mem_data_valid; +wire src_mem_data_last; +wire [DATA_WIDTH-1:0] src_mem_data; + +wire dest_beat; +wire dest_last_beat; +wire dest_last; +wire [ID_WIDTH-1:0] dest_src_id; +wire [ADDRESS_WIDTH-1:0] dest_raddr; +wire [ID_WIDTH-2:0] dest_id_reduced_next; +wire [ID_WIDTH-1:0] dest_id_next_inc; +wire [ID_WIDTH-2:0] dest_id_reduced; +wire dest_burst_valid; +wire dest_burst_ready; +wire dest_ready; +wire [DATA_WIDTH-1:0] dest_mem_data; +wire dest_mem_data_ready; + +`include "inc_id.h" + +generate if (ID_WIDTH >= 3) begin + assign src_id_reduced = {src_id_reduced_msb,src_id[ID_WIDTH-3:0]}; + assign dest_id_reduced_next = {dest_id_reduced_msb_next,dest_id_next[ID_WIDTH-3:0]}; + assign dest_id_reduced = {dest_id_reduced_msb,dest_id[ID_WIDTH-3:0]}; +end else begin + assign src_id_reduced = src_id_reduced_msb; + assign dest_id_reduced_next = dest_id_reduced_msb_next; + assign dest_id_reduced = dest_id_reduced_msb; +end endgenerate + +assign src_beat = src_mem_data_valid & src_mem_data_ready; +assign src_last_beat = src_beat & src_mem_data_last; +assign src_waddr = {src_id_reduced,src_beat_counter}; + +always @(*) begin + if (src_last_beat == 1'b1) begin + src_id_next <= inc_id(src_id); + end else begin + src_id_next <= src_id; + end +end + +always @(posedge src_clk) begin + /* Ready if there is room for at least one full burst. */ + src_mem_data_ready <= (src_id_next[ID_WIDTH-1] == src_dest_id[ID_WIDTH-1] || + src_id_next[ID_WIDTH-2] == src_dest_id[ID_WIDTH-2] || + src_id_next[ID_WIDTH-3:0] != src_dest_id[ID_WIDTH-3:0]); +end + +always @(posedge src_clk) begin + if (src_reset == 1'b1) begin + src_id <= 'h00; + src_id_reduced_msb <= 1'b0; + end else begin + src_id <= src_id_next; + src_id_reduced_msb <= ^src_id_next[ID_WIDTH-1-:2]; + end +end + +always @(posedge src_clk) begin + if (src_reset == 1'b1) begin + src_beat_counter <= 'h00; + end else if (src_beat == 1'b1) begin + src_beat_counter <= src_beat_counter + 1'b1; + end +end + +always @(posedge src_clk) begin + if (src_last_beat == 1'b1) begin + burst_len_mem[src_id_reduced] <= src_beat_counter; + end +end + +assign dest_ready = ~dest_mem_data_valid | dest_mem_data_ready; +assign dest_last = dest_beat_counter == dest_burst_len; + +assign dest_beat = dest_valid & dest_ready; +assign dest_last_beat = dest_last & dest_beat; +assign dest_raddr = {dest_id_reduced,dest_beat_counter}; + +assign dest_burst_valid = dest_src_id != dest_id_next; +assign dest_burst_ready = ~dest_valid | dest_last_beat; + +/* + * The data valid signal for the destination side is asserted if there are one + * or more pending bursts. It is de-asserted if there are no more pending burst + * and it is the last beat of the current burst + */ +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_valid <= 1'b0; + end else if (dest_burst_valid == 1'b1) begin + dest_valid <= 1'b1; + end else if (dest_last_beat == 1'b1) begin + dest_valid <= 1'b0; + end +end + +/* + * The output register of the memory creates a extra clock cycle of latency on + * the data path. We need to handle this more the handshaking signals. If data + * is available in the memory it will be available one clock cycle later in the + * output register. + */ +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_mem_data_valid <= 1'b0; + end else if (dest_valid == 1'b1) begin + dest_mem_data_valid <= 1'b1; + end else if (dest_mem_data_ready == 1'b1) begin + dest_mem_data_valid <= 1'b0; + end +end + +assign dest_id_next_inc = inc_id(dest_id_next); + +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_id_next <= 'h00; + dest_id_reduced_msb_next <= 1'b0; + end else if (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1) begin + dest_id_next <= dest_id_next_inc; + dest_id_reduced_msb_next <= ^dest_id_next_inc[ID_WIDTH-1-:2]; + end +end + +always @(posedge dest_clk) begin + if (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1) begin + dest_burst_len <= burst_len_mem[dest_id_reduced_next]; + end +end + +always @(posedge dest_clk) begin + if (dest_burst_ready == 1'b1) begin + dest_id <= dest_id_next; + dest_id_reduced_msb <= dest_id_reduced_msb_next; + end +end + +always @(posedge dest_clk) begin + if (dest_reset == 1'b1) begin + dest_beat_counter <= 'h00; + end else if (dest_beat == 1'b1) begin + dest_beat_counter <= dest_beat_counter + 1'b1; + end +end + +axi_dmac_resize_src #( + .DATA_WIDTH_SRC (DATA_WIDTH_SRC), + .DATA_WIDTH_MEM (DATA_WIDTH) +) i_resize_src ( + .clk (src_clk), + .reset (src_reset), + + .src_data_valid (src_data_valid), + .src_data_ready (src_data_ready), + .src_data (src_data), + .src_data_last (src_data_last), + + .mem_data_valid (src_mem_data_valid), + .mem_data_ready (src_mem_data_ready), + .mem_data (src_mem_data), + .mem_data_last (src_mem_data_last) +); + +ad_mem #( + .DATA_WIDTH (DATA_WIDTH), + .ADDRESS_WIDTH (ADDRESS_WIDTH) +) i_mem ( + .clka (src_clk), + .wea (src_beat), + .addra (src_waddr), + .dina (src_mem_data), + + .clkb (dest_clk), + .reb (dest_beat), + .addrb (dest_raddr), + .doutb (dest_mem_data) +); + +axi_dmac_resize_dest #( + .DATA_WIDTH_DEST (DATA_WIDTH_DEST), + .DATA_WIDTH_MEM (DATA_WIDTH) +) i_resize_dest ( + .clk (dest_clk), + .reset (dest_reset), + + .mem_data_valid (dest_mem_data_valid), + .mem_data_ready (dest_mem_data_ready), + .mem_data (dest_mem_data), + .mem_data_last (dest_mem_data_last), + + .dest_data_valid (dest_data_valid), + .dest_data_ready (dest_data_ready), + .dest_data (dest_data), + .dest_data_last (dest_data_last) +); + +sync_bits #( + .NUM_OF_BITS (ID_WIDTH), + .ASYNC_CLK (ASYNC_CLK) +) i_dest_sync_id ( + .in (src_id), + .out_clk (dest_clk), + .out_resetn (1'b1), + .out (dest_src_id) +); + +sync_bits #( + .NUM_OF_BITS (ID_WIDTH), + .ASYNC_CLK (ASYNC_CLK) +) i_src_sync_id ( + .in (dest_id), + .out_clk (src_clk), + .out_resetn (1'b1), + .out (src_dest_id) +); + +endmodule diff --git a/library/axi_dmac/axi_dmac_constr.sdc b/library/axi_dmac/axi_dmac_constr.sdc index b9a05e28c..a706cb8fb 100644 --- a/library/axi_dmac/axi_dmac_constr.sdc +++ b/library/axi_dmac/axi_dmac_constr.sdc @@ -4,6 +4,9 @@ set_false_path -to [get_registers *axi_dmac*cdc_sync_stage1*] set_false_path -from [get_registers *axi_dmac*cdc_sync_fifo_ram*] set_false_path -from [get_registers *axi_dmac*eot_mem*] +# Burst memory +set_false_path -from [get_registers *axi_dmac*burst_len_mem*] + # Reset manager set_false_path \ -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|do_reset}] \ diff --git a/library/axi_dmac/axi_dmac_constr.ttcl b/library/axi_dmac/axi_dmac_constr.ttcl index fb3cb041b..556f9089d 100644 --- a/library/axi_dmac/axi_dmac_constr.ttcl +++ b/library/axi_dmac/axi_dmac_constr.ttcl @@ -131,13 +131,20 @@ set_max_delay -quiet -datapath_only \ set_max_delay -quiet -datapath_only \ -from $src_clk \ -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_fifo/i_address_gray/i_waddr_sync* && IS_SEQUENTIAL}] \ + -filter {NAME =~ *i_store_and_forward/i_dest_sync_id* && IS_SEQUENTIAL}] \ [get_property -min PERIOD $src_clk] set_max_delay -quiet -datapath_only \ -from $dest_clk \ -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_fifo/i_address_gray/i_raddr_sync* && IS_SEQUENTIAL}] \ + -filter {NAME =~ *i_store_and_forward/i_src_sync_id* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -through [get_cells -quiet -hier \ + -filter {IS_SEQUENTIAL && NAME =~ *i_store_and_forward/burst_len_mem_reg*}] \ + -to $dest_clk \ [get_property -min PERIOD $dest_clk] <: } :> diff --git a/library/axi_dmac/axi_dmac_hw.tcl b/library/axi_dmac/axi_dmac_hw.tcl index 3ae53b011..2cb429f67 100644 --- a/library/axi_dmac/axi_dmac_hw.tcl +++ b/library/axi_dmac/axi_dmac_hw.tcl @@ -16,19 +16,17 @@ set_module_property VALIDATION_CALLBACK axi_dmac_validate ad_ip_files axi_dmac [list \ $ad_hdl_dir/library/util_cdc/sync_bits.v \ - $ad_hdl_dir/library/util_cdc/sync_gray.v \ $ad_hdl_dir/library/common/up_axi.v \ - $ad_hdl_dir/library/util_axis_resize/util_axis_resize.v \ $ad_hdl_dir/library/util_axis_fifo/util_axis_fifo.v \ - $ad_hdl_dir/library/util_axis_fifo/address_gray.v \ - $ad_hdl_dir/library/util_axis_fifo/address_gray_pipelined.v \ - $ad_hdl_dir/library/util_axis_fifo/address_sync.v \ $ad_hdl_dir/library/common/ad_mem.v \ inc_id.h \ resp.h \ + axi_dmac_burst_memory.v \ axi_dmac_regmap.v \ axi_dmac_regmap_request.v \ axi_dmac_reset_manager.v \ + axi_dmac_resize_dest.v \ + axi_dmac_resize_src.v \ axi_dmac_transfer.v \ address_generator.v \ data_mover.v \ @@ -50,7 +48,7 @@ ad_ip_files axi_dmac [list \ ] # Disable dual-clock RAM read-during-write behaviour warning. -set_qip_strings { "set_instance_assignment -name MESSAGE_DISABLE 276027 -entity util_axis_fifo" } +set_qip_strings { "set_instance_assignment -name MESSAGE_DISABLE 276027 -entity axi_dmac_burst_memory" } # parameters diff --git a/library/axi_dmac/axi_dmac_ip.tcl b/library/axi_dmac/axi_dmac_ip.tcl index 649d306d2..743b9b6e5 100644 --- a/library/axi_dmac/axi_dmac_ip.tcl +++ b/library/axi_dmac/axi_dmac_ip.tcl @@ -5,12 +5,16 @@ source $ad_hdl_dir/library/scripts/adi_ip.tcl adi_ip_create axi_dmac adi_ip_files axi_dmac [list \ + "$ad_hdl_dir/library/common/ad_mem.v" \ "$ad_hdl_dir/library/common/up_axi.v" \ "inc_id.h" \ "resp.h" \ + "axi_dmac_burst_memory.v" \ "axi_dmac_regmap.v" \ "axi_dmac_regmap_request.v" \ "axi_dmac_reset_manager.v" \ + "axi_dmac_resize_dest.v" \ + "axi_dmac_resize_src.v" \ "axi_dmac_transfer.v" \ "address_generator.v" \ "data_mover.v" \ @@ -37,7 +41,6 @@ adi_ip_ttcl axi_dmac "axi_dmac_constr.ttcl" adi_ip_bd axi_dmac "bd/bd.tcl" adi_ip_add_core_dependencies { \ - analog.com:user:util_axis_resize:1.0 \ analog.com:user:util_axis_fifo:1.0 \ analog.com:user:util_cdc:1.0 \ } diff --git a/library/axi_dmac/axi_dmac_resize_dest.v b/library/axi_dmac/axi_dmac_resize_dest.v new file mode 100644 index 000000000..1cffc45f5 --- /dev/null +++ b/library/axi_dmac/axi_dmac_resize_dest.v @@ -0,0 +1,113 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +module axi_dmac_resize_dest #( + parameter DATA_WIDTH_DEST = 64, + parameter DATA_WIDTH_MEM = 64 +) ( + input clk, + input reset, + + input mem_data_valid, + output mem_data_ready, + input [DATA_WIDTH_MEM-1:0] mem_data, + input mem_data_last, + + output dest_data_valid, + input dest_data_ready, + output [DATA_WIDTH_DEST-1:0] dest_data, + output dest_data_last +); + +/* + * Resize the data width between the burst memory and the destination interface + * if necessary. + */ + +generate if (DATA_WIDTH_DEST == DATA_WIDTH_MEM) begin + assign dest_data_valid = mem_data_valid; + assign dest_data = mem_data; + assign dest_data_last = mem_data_last; + assign mem_data_ready = dest_data_ready; +end else begin + + localparam RATIO = DATA_WIDTH_MEM / DATA_WIDTH_DEST; + + reg [$clog2(RATIO)-1:0] count = 'h0; + reg valid = 1'b0; + reg [RATIO-1:0] last = 'h0; + reg [DATA_WIDTH_MEM-1:0] data = 'h0; + + wire last_beat; + + assign last_beat = count == RATIO - 1; + + always @(posedge clk) begin + if (reset == 1'b1) begin + valid <= 1'b0; + end else if (mem_data_valid == 1'b1) begin + valid <= 1'b1; + end else if (last_beat == 1'b1 && dest_data_ready == 1'b1) begin + valid <= 1'b0; + end + end + + always @(posedge clk) begin + if (reset == 1'b1) begin + count <= 'h0; + end else if (dest_data_ready == 1'b1 && dest_data_valid == 1'b1) begin + count <= count + 1; + end + end + + assign mem_data_ready = ~valid | (dest_data_ready & last_beat); + + always @(posedge clk) begin + if (mem_data_ready == 1'b1) begin + data <= mem_data; + last <= {mem_data_last,{RATIO-1{1'b0}}}; + end else if (dest_data_ready == 1'b1) begin + data[DATA_WIDTH_MEM-DATA_WIDTH_DEST-1:0] <= data[DATA_WIDTH_MEM-1:DATA_WIDTH_DEST]; + last[RATIO-2:0] <= last[RATIO-1:1]; + end + end + + assign dest_data_valid = valid; + assign dest_data = data[DATA_WIDTH_DEST-1:0]; + assign dest_data_last = last[0]; + +end endgenerate + +endmodule diff --git a/library/axi_dmac/axi_dmac_resize_src.v b/library/axi_dmac/axi_dmac_resize_src.v new file mode 100644 index 000000000..9fa730990 --- /dev/null +++ b/library/axi_dmac/axi_dmac_resize_src.v @@ -0,0 +1,105 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +/* + * Resize the data width between the source interface and the burst memory + * if necessary. + */ + +module axi_dmac_resize_src #( + parameter DATA_WIDTH_SRC = 64, + parameter DATA_WIDTH_MEM = 64 +) ( + input clk, + input reset, + + input src_data_valid, + output src_data_ready, + input [DATA_WIDTH_SRC-1:0] src_data, + input src_data_last, + + output mem_data_valid, + input mem_data_ready, + output [DATA_WIDTH_MEM-1:0] mem_data, + output mem_data_last +); + +generate if (DATA_WIDTH_SRC == DATA_WIDTH_MEM) begin + assign mem_data_valid = src_data_valid; + assign src_data_ready = mem_data_ready; + assign mem_data = src_data; + assign mem_data_last = src_data_last; +end else begin + + localparam RATIO = DATA_WIDTH_MEM / DATA_WIDTH_SRC; + + reg [RATIO-1:0] mask = 'h1; + reg valid = 1'b0; + reg last = 1'b0; + reg [DATA_WIDTH_MEM-1:0] data = 'h0; + + always @(posedge clk) begin + if (reset == 1'b1) begin + valid <= 1'b0; + mask <= 'h1; + end else if (src_data_valid == 1'b1 && src_data_ready == 1'b1) begin + valid <= mask[RATIO-1]; + mask <= {mask[RATIO-2:0],mask[RATIO-1]}; + end else if (mem_data_ready == 1'b1) begin + valid <= 1'b0; + end + end + + integer i; + + always @(posedge clk) begin + if (src_data_ready == 1'b1) begin + for (i = 0; i < RATIO; i = i+1) begin + if (mask[i] == 1'b1) begin + data[i*DATA_WIDTH_SRC+:DATA_WIDTH_SRC] <= src_data; + end + end + last <= src_data_last; + end + end + + assign src_data_ready = ~valid | mem_data_ready; + assign mem_data_valid = valid; + assign mem_data = data; + assign mem_data_last = last; + +end endgenerate + +endmodule diff --git a/library/axi_dmac/request_arb.v b/library/axi_dmac/request_arb.v index 1f1c4a7a4..c60ec8304 100644 --- a/library/axi_dmac/request_arb.v +++ b/library/axi_dmac/request_arb.v @@ -175,11 +175,6 @@ localparam DMA_TYPE_FIFO = 2; localparam DMA_ADDRESS_WIDTH_DEST = DMA_AXI_ADDR_WIDTH - BYTES_PER_BEAT_WIDTH_DEST; localparam DMA_ADDRESS_WIDTH_SRC = DMA_AXI_ADDR_WIDTH - BYTES_PER_BEAT_WIDTH_SRC; -localparam DMA_DATA_WIDTH = DMA_DATA_WIDTH_SRC < DMA_DATA_WIDTH_DEST ? - DMA_DATA_WIDTH_DEST : DMA_DATA_WIDTH_SRC; - - - // Bytes per burst is the same for both dest and src, but bytes per beat may // differ, so beats per burst may also differ localparam BYTES_PER_BURST_WIDTH = @@ -233,12 +228,9 @@ wire [ID_WIDTH-1:0] dest_response_id; wire dest_valid; wire dest_ready; wire [DMA_DATA_WIDTH_DEST-1:0] dest_data; -wire dest_fifo_repacked_valid; -wire dest_fifo_repacked_ready; -wire [DMA_DATA_WIDTH_DEST-1:0] dest_fifo_repacked_data; wire dest_fifo_valid; wire dest_fifo_ready; -wire [DMA_DATA_WIDTH-1:0] dest_fifo_data; +wire [DMA_DATA_WIDTH_DEST-1:0] dest_fifo_data; wire src_req_valid; wire src_req_ready; @@ -260,12 +252,11 @@ wire [ID_WIDTH-1:0] src_response_id; wire src_valid; wire src_ready; wire [DMA_DATA_WIDTH_SRC-1:0] src_data; +wire src_last; wire src_fifo_valid; wire src_fifo_ready; wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data; -wire src_fifo_repacked_valid; -wire src_fifo_repacked_ready; -wire [DMA_DATA_WIDTH-1:0] src_fifo_repacked_data; +wire src_fifo_last; wire response_dest_valid; wire response_dest_ready = 1'b1; @@ -555,6 +546,7 @@ dmac_src_mm_axi #( .fifo_valid(src_valid), .fifo_ready(src_ready), .fifo_data(src_data), + .fifo_last(src_last), .m_axi_arready(m_axi_arready), .m_axi_arvalid(m_axi_arvalid), @@ -625,6 +617,7 @@ dmac_src_axi_stream #( .fifo_valid(src_valid), .fifo_ready(src_ready), .fifo_data(src_data), + .fifo_last(src_last), .s_axis_valid(s_axis_valid), .s_axis_ready(s_axis_ready), @@ -680,6 +673,7 @@ dmac_src_fifo_inf #( .fifo_valid(src_valid), .fifo_ready(src_ready), .fifo_data(src_data), + .fifo_last(src_last), .en(fifo_wr_en), .din(fifo_wr_din), @@ -726,7 +720,7 @@ sync_bits #( ); axi_register_slice #( - .DATA_WIDTH(DMA_DATA_WIDTH_SRC), + .DATA_WIDTH(DMA_DATA_WIDTH_SRC + 1), .FORWARD_REGISTERED(AXI_SLICE_SRC), .BACKWARD_REGISTERED(AXI_SLICE_SRC) ) i_src_slice ( @@ -734,59 +728,31 @@ axi_register_slice #( .resetn(src_resetn), .s_axi_valid(src_valid), .s_axi_ready(src_ready), - .s_axi_data(src_data), + .s_axi_data({src_data,src_last}), .m_axi_valid(src_fifo_valid), .m_axi_ready(src_fifo_ready), - .m_axi_data(src_fifo_data) + .m_axi_data({src_fifo_data,src_fifo_last}) ); -util_axis_resize #( - .SLAVE_DATA_WIDTH(DMA_DATA_WIDTH_SRC), - .MASTER_DATA_WIDTH(DMA_DATA_WIDTH) -) i_src_repack ( - .clk(src_clk), - .resetn(src_resetn), - .s_valid(src_fifo_valid), - .s_ready(src_fifo_ready), - .s_data(src_fifo_data), - .m_valid(src_fifo_repacked_valid), - .m_ready(src_fifo_repacked_ready), - .m_data(src_fifo_repacked_data) -); - -util_axis_fifo #( - .DATA_WIDTH(DMA_DATA_WIDTH), - .ADDRESS_WIDTH($clog2(MAX_BYTES_PER_BURST / (DMA_DATA_WIDTH / 8) * FIFO_SIZE)), +axi_dmac_burst_memory #( + .DATA_WIDTH_SRC(DMA_DATA_WIDTH_SRC), + .DATA_WIDTH_DEST(DMA_DATA_WIDTH_DEST), + .ID_WIDTH(ID_WIDTH), + .MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST), .ASYNC_CLK(ASYNC_CLK_SRC_DEST) -) i_fifo ( - .s_axis_aclk(src_clk), - .s_axis_aresetn(src_resetn), - .s_axis_valid(src_fifo_repacked_valid), - .s_axis_ready(src_fifo_repacked_ready), - .s_axis_data(src_fifo_repacked_data), - .s_axis_empty(), - .s_axis_room(), +) i_store_and_forward ( + .src_clk(src_clk), + .src_reset(~src_resetn), + .src_data_valid(src_fifo_valid), + .src_data_ready(src_fifo_ready), + .src_data(src_fifo_data), + .src_data_last(src_fifo_last), - .m_axis_aclk(dest_clk), - .m_axis_aresetn(dest_resetn), - .m_axis_valid(dest_fifo_valid), - .m_axis_ready(dest_fifo_ready), - .m_axis_data(dest_fifo_data), - .m_axis_level() -); - -util_axis_resize #( - .SLAVE_DATA_WIDTH(DMA_DATA_WIDTH), - .MASTER_DATA_WIDTH(DMA_DATA_WIDTH_DEST) -) i_dest_repack ( - .clk(dest_clk), - .resetn(dest_resetn), - .s_valid(dest_fifo_valid), - .s_ready(dest_fifo_ready), - .s_data(dest_fifo_data), - .m_valid(dest_fifo_repacked_valid), - .m_ready(dest_fifo_repacked_ready), - .m_data(dest_fifo_repacked_data) + .dest_clk(dest_clk), + .dest_reset(~dest_resetn), + .dest_data_valid(dest_fifo_valid), + .dest_data_ready(dest_fifo_ready), + .dest_data(dest_fifo_data) ); wire _dest_valid; @@ -799,9 +765,9 @@ axi_register_slice #( ) i_dest_slice2 ( .clk(dest_clk), .resetn(dest_resetn), - .s_axi_valid(dest_fifo_repacked_valid), - .s_axi_ready(dest_fifo_repacked_ready), - .s_axi_data(dest_fifo_repacked_data), + .s_axi_valid(dest_fifo_valid), + .s_axi_ready(dest_fifo_ready), + .s_axi_data(dest_fifo_data), .m_axi_valid(_dest_valid), .m_axi_ready(_dest_ready), .m_axi_data(_dest_data) diff --git a/library/axi_dmac/src_axi_mm.v b/library/axi_dmac/src_axi_mm.v index 004262366..6f7b04519 100644 --- a/library/axi_dmac/src_axi_mm.v +++ b/library/axi_dmac/src_axi_mm.v @@ -69,6 +69,7 @@ module dmac_src_mm_axi #( output fifo_valid, input fifo_ready, output [DMA_DATA_WIDTH-1:0] fifo_data, + output fifo_last, // Read address input m_axi_arready, @@ -134,6 +135,7 @@ dmac_address_generator #( assign fifo_valid = m_axi_rvalid; assign m_axi_rready = fifo_ready; assign fifo_data = m_axi_rdata; +assign fifo_last = m_axi_rlast; /* * There is a requirement that data_id <= address_id (modulo 2**ID_WIDTH). We diff --git a/library/axi_dmac/src_axi_stream.v b/library/axi_dmac/src_axi_stream.v index 221d407ee..b55910006 100644 --- a/library/axi_dmac/src_axi_stream.v +++ b/library/axi_dmac/src_axi_stream.v @@ -60,6 +60,7 @@ module dmac_src_axi_stream #( input fifo_ready, output fifo_valid, output [S_AXIS_DATA_WIDTH-1:0] fifo_data, + output fifo_last, input req_valid, output req_ready, @@ -77,7 +78,6 @@ wire sync = s_axis_user[0]; wire has_sync = ~needs_sync | sync; wire data_valid; wire data_ready; -wire fifo_last; assign data = transfer_abort == 1'b1 ? {S_AXIS_DATA_WIDTH{1'b0}} : s_axis_data; assign data_valid = (s_axis_valid & has_sync) | transfer_abort; @@ -102,7 +102,7 @@ always @(posedge s_axis_aclk) begin if (s_axis_aresetn == 1'b0) begin transfer_abort <= 1'b0; end else if (data_ready == 1'b1 && data_valid == 1'b1) begin - if (fifo_last == 1'b1 && req_xlast_d == 1'b1) begin + if (fifo_last == 1'b1 && eot == 1'b1 && req_xlast_d == 1'b1) begin transfer_abort <= 1'b0; end else if (s_axis_last == 1'b1) begin transfer_abort <= 1'b1; @@ -120,8 +120,7 @@ dmac_data_mover # ( .ID_WIDTH(ID_WIDTH), .DATA_WIDTH(S_AXIS_DATA_WIDTH), .DISABLE_WAIT_FOR_ID(0), - .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH), - .LAST(1) + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH) ) i_data_mover ( .clk(s_axis_aclk), .resetn(s_axis_aresetn), diff --git a/library/axi_dmac/src_fifo_inf.v b/library/axi_dmac/src_fifo_inf.v index a5a1e3883..bcee4e25e 100644 --- a/library/axi_dmac/src_fifo_inf.v +++ b/library/axi_dmac/src_fifo_inf.v @@ -58,6 +58,7 @@ module dmac_src_fifo_inf #( input fifo_ready, output fifo_valid, output [DATA_WIDTH-1:0] fifo_data, + output fifo_last, input req_valid, output req_ready, @@ -119,7 +120,7 @@ dmac_data_mover # ( .m_axi_ready(fifo_ready), .m_axi_valid(fifo_valid), .m_axi_data(fifo_data), - .m_axi_last() + .m_axi_last(fifo_last) ); endmodule diff --git a/library/axi_dmac/tb/dma_read_shutdown_tb b/library/axi_dmac/tb/dma_read_shutdown_tb index 8a0c94615..dd035c8e8 100755 --- a/library/axi_dmac/tb/dma_read_shutdown_tb +++ b/library/axi_dmac/tb/dma_read_shutdown_tb @@ -4,13 +4,14 @@ SOURCE="$0.v" SOURCE+=" axi_read_slave.v axi_slave.v" SOURCE+=" ../axi_dmac_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" SOURCE+=" ../2d_transfer.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" SOURCE+=" ../dest_fifo_inf.v" SOURCE+=" ../src_axi_mm.v ../address_generator.v ../response_generator.v" -SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v ../../util_axis_fifo/address_gray_pipelined.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" SOURCE+=" ../../common/ad_mem.v" -SOURCE+=" ../../util_cdc/sync_bits.v ../../util_cdc/sync_gray.v" -SOURCE+=" ../../util_axis_resize/util_axis_resize.v" cd `dirname $0` source run_tb.sh diff --git a/library/axi_dmac/tb/dma_read_tb b/library/axi_dmac/tb/dma_read_tb index 678f2f8bd..a61e6f978 100755 --- a/library/axi_dmac/tb/dma_read_tb +++ b/library/axi_dmac/tb/dma_read_tb @@ -3,13 +3,14 @@ SOURCE="dma_read_tb.v" SOURCE+=" axi_read_slave.v axi_slave.v" SOURCE+=" ../axi_dmac_transfer.v ../2d_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" SOURCE+=" ../dest_fifo_inf.v" SOURCE+=" ../src_axi_mm.v ../address_generator.v ../response_generator.v" -SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v ../../util_axis_fifo/address_gray_pipelined.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" SOURCE+=" ../../common/ad_mem.v" -SOURCE+=" ../../util_cdc/sync_bits.v ../../util_cdc/sync_gray.v" -SOURCE+=" ../../util_axis_resize/util_axis_resize.v" cd `dirname $0` source run_tb.sh diff --git a/library/axi_dmac/tb/dma_write_shutdown_tb b/library/axi_dmac/tb/dma_write_shutdown_tb index 8a3dd76e3..cc250e5c6 100755 --- a/library/axi_dmac/tb/dma_write_shutdown_tb +++ b/library/axi_dmac/tb/dma_write_shutdown_tb @@ -4,13 +4,14 @@ SOURCE="$0.v" SOURCE+=" axi_write_slave.v axi_slave.v" SOURCE+=" ../axi_dmac_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" SOURCE+=" ../2d_transfer.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" SOURCE+=" ../src_fifo_inf.v" SOURCE+=" ../dest_axi_mm.v ../response_handler.v ../address_generator.v" -SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v ../../util_axis_fifo/address_gray_pipelined.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" SOURCE+=" ../../common/ad_mem.v" -SOURCE+=" ../../util_cdc/sync_bits.v ../../util_cdc/sync_gray.v" -SOURCE+=" ../../util_axis_resize/util_axis_resize.v" cd `dirname $0` source run_tb.sh diff --git a/library/axi_dmac/tb/dma_write_tb b/library/axi_dmac/tb/dma_write_tb index e15494094..de24fdceb 100755 --- a/library/axi_dmac/tb/dma_write_tb +++ b/library/axi_dmac/tb/dma_write_tb @@ -3,13 +3,14 @@ SOURCE="dma_write_tb.v" SOURCE+=" axi_write_slave.v axi_slave.v" SOURCE+=" ../axi_dmac_transfer.v ../2d_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" +SOURCE+=" ../axi_dmac_resize_src.v ../axi_dmac_resize_dest.v" +SOURCE+=" ../axi_dmac_burst_memory.v" SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" SOURCE+=" ../src_fifo_inf.v" SOURCE+=" ../dest_axi_mm.v ../response_handler.v ../address_generator.v" -SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v ../../util_axis_fifo/address_gray_pipelined.v" +SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v" +SOURCE+=" ../../util_cdc/sync_bits.v" SOURCE+=" ../../common/ad_mem.v" -SOURCE+=" ../../util_cdc/sync_bits.v ../../util_cdc/sync_gray.v" -SOURCE+=" ../../util_axis_resize/util_axis_resize.v" cd `dirname $0` source run_tb.sh