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