By explicitly pairing the clock running the interface with the interface
in Vivado it allows for better timing analysis and remove some 'CRITICAL
WARNINGS'.
The memory is addressable using the AXIS ports in 64 bit (8 byte) chunks. Thus
when allocating memory from CMA region, the start address needs to be 64 bit
aligned, not page aligned. This change will thus reduce the 'padding' at the
end of arrays and thus RAM.
This devicetree code is an altered version of the
'arch/arm/boot/dts/zynq-7000.dtsi' file found in the linux-xlnx Xilinx
repo, master branch commit (da2d296bb6b89f7bc7644f6b552b9766ac1c17d5).
The only thing that was added was the following axis node:-
```
axis: axis@43C00000 {
compatible = "xlnx,axis-1.00";
reg = < 0x43C00000 0x10000 >;
xlnx,num-mem = <0x1>;
xlnx,num-reg = <0x20>;
xlnx,s-axi-min-size = <0x1ff>;
xlnx,slv-awidth = <0x20>;
xlnx,slv-dwidth = <0x20>;
};
```
Similar functions could be constructed using calls to the already existing
functions, however, it seems more efficient to add them to the library in case
the application cannot optimizes external library calls.
The uio driver exports files to the /sys directory, one of which gives the RAM
memory offset for the *mem* CMA array. This will be needed when giving address
to the axis ports, it is thus read from the file during the init function call.
Arrays that will be used to pass data between the host and fpga need to be page
aligned and be slices of the DMA array the driver has reserved. These new
functions allocate slices from the DMA array and ensures that the starting
address is page aligned.
The driver sets ups a DMA contiguous array that will be used as a memory area
to share data between the PS and PL. The library memory maps this DMA array to
make it available to the host applications. The array is cache coherent and
thus data written or read from it bypass the CPU cache and read/write directly
from main memory. This ensures that the data is always the same between the
host and fpga but at a cost of long data accesses from the host CPU.
Add a High Performance port (HP0) to the zedboard_axis project and
connect a AXIS module that can read and write to the main memory using
HP0. Add two small applications that test writing and reading from
memory.
The application takes one argument, the number (or length) of data to be
written to the memory.
The physical address in main memory that is going to be written to is the
address of the CMA memory region on my currently running system.
Because the axis modules are minimalist, it assumes that all
transactions are performed without error and that transaction processing
is performed in-order. Thus the transaction IDs can safely be set to
zero. Doing so also fixes a bug in the write path that had prevented
multiple burst of data being sent. This was due to the fact that the
write data burst ID needs to have the same ID as the write address. But
the write address module was incrementing the ID while the write data ID
was not being set at all.
The axis module instantiates the AXI read and write path modules. It
performs a simple stream over the AXI port interface with no error
checking. It is configured by first addressing the module and then
sending a physical memory address and the number of streaming words to
be written.
The streaming interface is not exactly like the Xilinx stream interface
in that the data is always valid when the valid flag is high, the ready
flag being low does not invalidate the data but is used to signal up
stream to stop sending data. Down stream has a buffer able to absorb to
incoming valid data until such time as up stream stop sending.
This script copies all Verilog file from the hdl directories into a
'sim' directory. It then uses the Icarus Verilog simulator to run the
desired modules testbench.
Move the "util/zynq-axis-completion.bash" file into your home directory
and save it as a 'dot' file. Then add the code snippet in the header of
the file into your dot bashrc file.
Under "Design Sources" right click the "system_i" board design. From the
menu select "Create HDL Wrapper" to generate the system top file for the
project.
Within the "Block Diagram" areas "Diagram" tab select "Add IP". From the list
that appears select "AXI Interconnect".
Double click on the new AXI Interconnect block to customise it. Reduce
the number of master ports to 1.
In the right hand "Signals" tab drag all "Unconnected Clocks" to the
ps7/FCLK_CLK0 Clock Domain (there should be a few).
Connect the AXI Interconnect resets to the ps7 the FCLK_RESET0_N reset.
Click on the "S00_AXI" pin in the new AXI Interconnect and use "Connection
Mode" to connect it to the ps7 GP0 port.
Right click "M00_AXI" pin in the new AXI Interconnect and select "Make
External" from the drop down menu.
Double click the newly created "M00_AXI" external port to customise. Set
protocol as "AXI4Lite".
In "Address Editor" tab, right click "ps7"->"Data"->"Unmapped
Slaves"->"M00_AXI" and select "Assign Address".
In the "Block Design" "Diagram" tab right click and select "Create Port..."
from the drop down menu. In the "Create Port" dialog box name the port
"axi_clk", set its direction to "Output" and type to "Clock".
Click on the FCLK_CLK0 pin on the ps7 block and use the "Connection Mode" to
connect the FCLK_CLK0" to the new "axi_clk" port.
Create another port named "axi_rst_n", direction "Output" and type "Reset".
Click on the "axi_rst_n" port and use the "Connection Mode" to connect it to
the reset tree being used by the axi_dma module (not to FCLK_RESET0_N".
Open the project in the Vivado GUI. In the left hand "Flow Navigator" area
select the "Create Block Design". When prompted for a name, use "system".
A green bar appears at the top of the "Block Design" areas "Diagram" tab
prompting to "Add IP". Select to add ip and from the list that appear select
"ZYNQ7 Processing System" (2nd from the end). Click on the processing systems
block and rename to "ps7" from the "Block Properties". The green bar will now
be prompting you to run "Block Automation", select this and the ps7 will be
reconfigured with the Zedboard defaults.