axi_sram.sv (4263B)
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 module axi_sram( 18 input clk, 19 axi_ifc.slave s 20 ); 21 22 // inherit configuration from AXI interface 23 // sadly this does not work with localparam (at least in verilator) 24 `define IWIDTH $bits(s.awid) 25 `define AWIDTH $bits(s.awaddr) 26 `define DWIDTH $bits(s.wdata) 27 `define LWIDTH $bits(s.awlen) 28 29 // LIMITATIONS / TODO 30 // - only supports INCR bursts (and treats all bursts as INCR type) 31 // - investigate raising BVALID earlier to possibly save a cycle at EOB 32 33 typedef enum reg[1:0] { W_IDLE, W_DATA, W_ACK } wstate_t; 34 wstate_t wstate = W_IDLE; 35 wstate_t next_wstate; 36 37 wire do_mem_wr; 38 39 reg [`IWIDTH-1:0]next_bid; 40 reg next_awready; 41 reg next_wready; 42 reg next_bvalid; 43 44 reg [`AWIDTH-1:0]waddr = 0; 45 reg [`AWIDTH-1:0]next_waddr; 46 47 wire [`AWIDTH-1:0]waddr_plus_four; 48 assign waddr_plus_four = waddr + 32'h4; 49 50 assign do_mem_wr = s.wvalid & s.wready; 51 52 always_comb begin 53 next_wstate = wstate; 54 next_waddr = waddr; 55 next_bid = s.bid; 56 next_awready = 0; 57 next_wready = 0; 58 next_bvalid = 0; 59 case (wstate) 60 W_IDLE: begin 61 if (s.awvalid & s.awready) begin 62 next_waddr = s.awaddr; 63 next_bid = s.awid; 64 next_wstate = W_DATA; 65 next_wready = 1; 66 end else begin 67 next_awready = 1; 68 end 69 end 70 W_DATA: begin 71 if (s.wvalid) begin 72 next_waddr = waddr_plus_four; 73 if (s.wlast) begin 74 next_wstate = W_ACK; 75 next_bvalid = 1; 76 end else begin 77 next_wready = 1; 78 end 79 end else begin 80 next_wready = 1; 81 end 82 end 83 W_ACK: begin 84 if (s.bready) begin 85 next_wstate = W_IDLE; 86 next_waddr = s.awaddr; 87 next_awready = 1; 88 end else begin 89 next_bvalid = 1; 90 end 91 end 92 default: next_wstate = W_IDLE; 93 endcase 94 end 95 96 typedef enum reg[0:0] { R_IDLE, R_DATA } rstate_t; 97 rstate_t rstate = R_IDLE; 98 rstate_t next_rstate; 99 100 reg [`IWIDTH-1:0]next_rid; 101 reg next_arready; 102 reg next_rvalid; 103 reg next_rlast; 104 105 reg [`LWIDTH-1:0]rcount = 0; 106 reg [`LWIDTH-1:0]next_rcount; 107 reg [`AWIDTH-1:0]raddr = 0; 108 reg [`AWIDTH-1:0]next_raddr; 109 110 wire [`AWIDTH-1:0]raddr_plus_four; 111 assign raddr_plus_four = raddr + 32'h4; 112 113 wire rcount_is_zero; 114 assign rcount_is_zero = (rcount == 0); 115 116 wire rcount_is_one; 117 assign rcount_is_one = (rcount == 1); 118 119 always_comb begin 120 next_rstate = rstate; 121 next_raddr = raddr; 122 next_rid = s.rid; 123 next_rcount = rcount; 124 next_arready = 0; 125 next_rvalid = 0; 126 next_rlast = 0; 127 case (rstate) 128 R_IDLE: begin 129 if (s.arready & s.arvalid) begin 130 next_rstate = R_DATA; 131 next_raddr = s.araddr; 132 next_rid = s.arid; 133 next_rcount = s.arlen; 134 next_rvalid = 1; 135 136 // special case for 1-beat bursts 137 if (s.arlen == 0) 138 next_rlast = 1; 139 end else begin 140 next_arready = 1; 141 end 142 end 143 R_DATA: begin 144 if (s.rready & s.rvalid) begin 145 next_raddr = raddr_plus_four; 146 next_rcount = rcount - 1; 147 if (rcount_is_zero) begin 148 next_rstate = R_IDLE; 149 next_arready = 1; 150 end else begin 151 if (rcount_is_one) 152 next_rlast = 1; 153 next_rvalid = 1; 154 end 155 end else begin 156 if (rcount_is_zero) 157 next_rlast = 1; 158 next_rvalid = 1; 159 end 160 end 161 endcase 162 end 163 164 assign s.bresp = 0; // always OK 165 assign s.rresp = 0; // always OK 166 167 always_ff @(posedge clk) begin 168 wstate <= next_wstate; 169 waddr <= next_waddr; 170 s.awready <= next_awready; 171 s.wready <= next_wready; 172 s.bvalid <= next_bvalid; 173 s.bid <= next_bid; 174 175 rstate <= next_rstate; 176 raddr <= next_raddr; 177 rcount <= next_rcount; 178 s.arready <= next_arready; 179 s.rvalid <= next_rvalid; 180 s.rlast <= next_rlast; 181 s.rid <= next_rid; 182 end 183 184 // --- sram ---- 185 186 reg [`DWIDTH-1:0]memory[0:4095]; 187 188 always @(posedge clk) begin 189 if (do_mem_wr) begin 190 $display("mem[%x] = %x", waddr, s.wdata); 191 memory[waddr[13:2]] <= s.wdata; 192 end 193 //TODO: only when needed: 194 s.rdata <= memory[next_raddr[13:2]]; 195 end 196 197 endmodule