zynq-sandbox

old FPGA projects for ZYNQ
git clone http://frotz.net/git/zynq-sandbox.git
Log | Files | Refs | README

axi_dma_writer.sv (3329B)


      1 // Copyright 2014 Brian Swetland <swetland@frotz.net>
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 `timescale 1ns/1ps
     16 
     17 // on the clock where start=1
     18 //   addr is the first address of the transfer
     19 //   burstlen is the transfer wordcount minus 1
     20 //   data is the first word of the transfer
     21 // on the clock where advance=1
     22 //   data advances to the next word of the transfer
     23 // busy is asserted from the cycle after start until transfer complete
     24 
     25 module axi_dma_writer(
     26 	input clk,
     27 	axi_ifc.master m,
     28 	input start,
     29 	input [31:0]addr,
     30 	input [3:0]burstlen,
     31 	input [31:0]data,
     32 	output reg busy = 0,
     33 	output advance
     34 	);
     35 
     36 localparam STATE_IDLE = 4'd0;
     37 localparam STATE_WADDR = 4'd1;
     38 localparam STATE_WDATA = 4'd2;
     39 localparam STATE_ACK = 4'd3;
     40 
     41 initial m.awvalid = 0;
     42 initial m.wvalid = 0;
     43 
     44 reg [31:0]waddr = 0;
     45 reg [31:0]waddr_next;
     46 
     47 reg [3:0]state = STATE_IDLE;
     48 reg [3:0]state_next;
     49 
     50 reg awvalid_next;
     51 reg wvalid_next;
     52 reg bready_next;
     53 reg wlast_next;
     54 
     55 reg [3:0]count = 15;
     56 reg [3:0]count_next;
     57 
     58 reg busy_next;
     59 
     60 wire count_is_zero = (count == 4'h0);
     61 wire count_is_one = (count == 4'h1);
     62 
     63 assign advance = m.wvalid & m.wready & busy;
     64 
     65 always_comb begin
     66 	state_next = state;
     67 	count_next = count;
     68 	waddr_next = waddr;
     69 	busy_next = busy;
     70 	awvalid_next = 0;
     71 	wvalid_next = 0;
     72 	bready_next = 0;
     73 	wlast_next = 0;
     74 
     75 	case (state)
     76 	STATE_IDLE: begin
     77 		if (start) begin
     78 			state_next = STATE_WADDR;
     79 			count_next = burstlen;
     80 			waddr_next = addr;
     81 			busy_next = 1;
     82 			awvalid_next = 1;
     83 		end
     84 	end
     85 	STATE_WADDR: begin
     86 		if (m.awready) begin
     87 			state_next = STATE_WDATA;
     88 			wvalid_next = 1;
     89 			wlast_next = count_is_zero;
     90 		end else begin
     91 			awvalid_next = 1;
     92 		end
     93 	end
     94 	STATE_WDATA: begin
     95 		if (count_is_zero) begin
     96 			if (m.wready) begin
     97 				state_next = STATE_ACK;
     98 				bready_next = 1;
     99 			end else begin
    100 				wvalid_next = 1;
    101 				wlast_next = 1;
    102 			end
    103 		end else begin
    104 			wvalid_next = 1;
    105 			if (m.wready) begin
    106 				if (count_is_one) begin
    107 					wlast_next = 1;
    108 				end
    109 				count_next = count - 1;
    110 			end
    111 		end
    112 	end
    113 	STATE_ACK: begin
    114 		if (m.bvalid) begin
    115 			state_next = STATE_IDLE;
    116 			busy_next = 0;
    117 		end else begin
    118 			bready_next = 1;
    119 		end
    120 	end
    121 	default: state_next = STATE_IDLE;
    122 	endcase
    123 end
    124 
    125 assign m.awid = 0;
    126 assign m.awburst = 1;
    127 assign m.awcache = 0;
    128 assign m.awsize = 2;
    129 assign m.awlen = count;
    130 assign m.awlock = 0;
    131 
    132 assign m.awaddr = waddr;
    133 assign m.wdata = data;
    134 assign m.wstrb = 4'b1111;
    135 
    136 always_ff @(posedge clk) begin
    137 	state <= state_next;
    138 	count <= count_next;
    139 	waddr <= waddr_next;
    140 	busy <= busy_next;
    141 	m.awvalid <= awvalid_next;
    142 	m.wvalid <= wvalid_next;
    143 	m.bready <= bready_next;
    144 	m.wlast <= wlast_next;
    145 end
    146 
    147 
    148 assign m.arid = 0;
    149 assign m.araddr = 0;
    150 assign m.arvalid = 0;
    151 assign m.arburst = 0;
    152 assign m.arcache = 0;
    153 assign m.arlen = 0;
    154 assign m.arsize = 0;
    155 assign m.arlock = 0;
    156 assign m.rready = 0;
    157 
    158 endmodule