zynq-sandbox

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit adcf8730a8a93d43ba0a57023a199ca975408a98
parent 7882653f822301801f5eb059769e2813ca3824ca
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 17 Nov 2014 02:38:39 -0800

axi_hp_dma_reader/writer: 64bit high performance dma (first cut)

These send back-to-back bursts (always 16 beats), but handle
the address/data/ack streams separately to attempt to minimize
cycles lost on state transitions and allow interconnects to
have as much information as possible (ie, that this read will
be followed by the next read, etc etc).

Diffstat:
Ahdl/axi_hp_dma_reader.sv | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahdl/axi_hp_dma_writer.sv | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 230 insertions(+), 0 deletions(-)

diff --git a/hdl/axi_hp_dma_reader.sv b/hdl/axi_hp_dma_reader.sv @@ -0,0 +1,108 @@ +// Copyright 2014 Brian Swetland <swetland@frotz.net> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +`timescale 1ns / 1ps + +module axi_hp_dma_reader( + input clk, + axi_ifc.reader m, + +// control interface + input [31:0]txn_addr, // bits 6:0 ignored + input [31:0]txn_count, // bits 6:0 ignored + input txn_start, + output reg txn_busy = 0, + output reg [31:0]cyc_count = 0, + +// data interface + output [DWIDTH-1:0]data, + output valid, + input ready + ); + +// TODO: make 32bit work +parameter DWIDTH = 64; + +assign m.arid = 0; +assign m.arlen = 15; +assign m.arsize = 2'b11; // dword +assign m.arburst = 2'b01; // incr +assign m.arlock = 0; +assign m.arcache = 0; + +logic [31:0]cyc_count_next; + +logic txn_busy_next; + +logic [31:0]araddr = 0; +logic [31:0]araddr_next; + +logic [15:0]arcount = 0; +logic [15:0]arcount_next; + +logic [19:0]rcount = 0; +logic [19:0]rcount_next; + +wire arcount_is_zero = (arcount == 0); +wire rcount_is_zero = (rcount == 0); + +assign m.araddr = araddr; +assign m.arvalid = (~arcount_is_zero); + +assign m.rready = (~rcount_is_zero) & ready; +assign data = m.rdata; + +assign valid = (~rcount_is_zero) & m.rvalid; + +always_comb begin + cyc_count_next = cyc_count; + araddr_next = araddr; + arcount_next = arcount; + rcount_next = rcount; + txn_busy_next = txn_busy; + + if ( m.rready & m.rvalid ) begin + rcount_next = rcount - 1; + end + + if ( m.arvalid & m.arready) begin + arcount_next = arcount - 1; + araddr_next = araddr + 128; + end + + if (txn_busy) begin + cyc_count_next = cyc_count + 1; + if (rcount_is_zero & arcount_is_zero) begin + txn_busy_next = 0; + end + end else begin + if (txn_start) begin + cyc_count_next = 0; + araddr_next = { txn_addr[31:7], 7'd0 }; + arcount_next = txn_count[22:7]; + rcount_next = { txn_count[22:7], 4'd0 }; + txn_busy_next = 1; + end + end +end + +always_ff @(posedge clk) begin + araddr <= araddr_next; + arcount <= arcount_next; + rcount <= rcount_next; + txn_busy <= txn_busy_next; + cyc_count <= cyc_count_next; +end + +endmodule diff --git a/hdl/axi_hp_dma_writer.sv b/hdl/axi_hp_dma_writer.sv @@ -0,0 +1,122 @@ +// Copyright 2014 Brian Swetland <swetland@frotz.net> +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +`timescale 1ns / 1ps + +module axi_hp_dma_writer( + input clk, + axi_ifc.writer m, + +// control interface + input [31:0]txn_addr, // bits 6:0 ignored + input [31:0]txn_count, // bits 6:0 ignored + input txn_start, + output reg txn_busy = 0, + output reg [31:0]cyc_count = 0, + +// data interface + input [DWIDTH-1:0]data, + input valid, + output ready + ); + +// TODO: make 32bit work +parameter DWIDTH = 64; + +assign m.awid = 0; +assign m.awlen = 15; +assign m.awsize = 2'b11; // dword +assign m.awburst = 2'b01; // incr +assign m.awlock = 0; +assign m.awcache = 0; +assign m.wstrb = 8'b11111111; +assign m.bready = 1; + +logic [31:0]cyc_count_next; + +logic txn_busy_next; + +logic [31:0]awaddr = 0; +logic [31:0]awaddr_next; + +logic [15:0]awcount = 0; +logic [15:0]awcount_next; + +logic [15:0]bcount = 0; +logic [15:0]bcount_next; + +logic [19:0]wcount = 0; +logic [19:0]wcount_next; + +wire awcount_is_zero = (awcount == 0); +wire wcount_is_zero = (wcount == 0); +wire bcount_is_zero = (bcount == 0); + +assign m.awaddr = awaddr; +assign m.awvalid = (~awcount_is_zero); + +assign m.wvalid = (~wcount_is_zero) & valid; +assign m.wlast = (wcount[3:0] == 4'd1); +assign m.wdata = data; + +assign ready = (~wcount_is_zero) & m.wready; + +always_comb begin + cyc_count_next = cyc_count; + awaddr_next = awaddr; + awcount_next = awcount; + bcount_next = bcount; + wcount_next = wcount; + txn_busy_next = txn_busy; + + if ( m.wready & m.wvalid ) begin + wcount_next = wcount - 1; + end + + if ( m.bvalid ) begin + bcount_next = bcount - 1; + end + + if ( m.awvalid & m.awready) begin + awcount_next = awcount - 1; + awaddr_next = awaddr + 128; + end + + if (txn_busy) begin + cyc_count_next = cyc_count + 1; + if (wcount_is_zero & awcount_is_zero & bcount_is_zero) begin + txn_busy_next = 0; + end + end else begin + if (txn_start) begin + cyc_count_next = 0; + awaddr_next = { txn_addr[31:7], 7'd0 }; + awcount_next = txn_count[22:7]; + bcount_next = txn_count[22:7]; + wcount_next = { txn_count[22:7], 4'd0 }; + txn_busy_next = 1; + end + end +end + +always_ff @(posedge clk) begin + awaddr <= awaddr_next; + awcount <= awcount_next; + bcount <= bcount_next; + wcount <= wcount_next; + txn_busy <= txn_busy_next; + cyc_count <= cyc_count_next; +end + +endmodule