zynq-sandbox

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

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