zynq-sandbox

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

axi_registers.sv (3862B)


      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 // AXI Register Bridge
     18 //
     19 // Reads and Writes may happen simultaneously
     20 //
     21 // Reads:
     22 //  o_rd=1 o_rreg=n on posedge clk
     23 //  i_rdata sampled on next posedge clk
     24 // Writes:
     25 //  o_wr=1 o_wreg=n o_wdata=w on posedge clk
     26 
     27 // TODO: deal with non-length-1 bursts
     28 
     29 module axi_registers (
     30 	input clk,
     31 
     32 	// AXI Interface
     33 	axi_ifc.slave s,
     34 
     35 	// Register File Interface
     36 	output reg [R_ADDR_WIDTH-1:0]o_rreg = 0,
     37 	output reg [R_ADDR_WIDTH-1:0]o_wreg = 0,
     38 	input wire [31:0]i_rdata,
     39 	output wire [31:0]o_wdata,
     40 	output reg o_rd = 0,
     41 	output wire o_wr
     42 	);
     43 
     44 parameter integer R_ADDR_WIDTH = 2;
     45 
     46 `define IWIDTH $bits(s.awid)
     47 
     48 typedef enum { W_ADDR, W_DATA, W_RESP } wstate_t;
     49 
     50 assign s.bresp = 0;
     51 assign s.rresp = 0;
     52 
     53 //reg [31:0]wdata = 0;
     54 //reg [31:0]wdata_next;
     55 
     56 wstate_t wstate = W_ADDR;
     57 wstate_t wstate_next;
     58 
     59 reg awready_next;
     60 reg wready_next;
     61 reg bvalid_next;
     62 
     63 reg [R_ADDR_WIDTH-1:0]wreg_next;
     64 reg [R_ADDR_WIDTH-1:0]rreg_next;
     65 
     66 assign o_wdata = s.wdata;
     67 assign o_wr = (s.wvalid & s.wready);
     68 
     69 reg [`IWIDTH-1:0]twid = 0;
     70 reg [`IWIDTH-1:0]twid_next;
     71 
     72 assign s.bid = twid;
     73 
     74 always_comb begin
     75 	wstate_next = wstate;
     76 	//wdata_next = wdata;
     77 	wreg_next = o_wreg;
     78 	twid_next = twid;
     79 	awready_next = 0;
     80 	wready_next = 0;
     81 	bvalid_next = 0;
     82 	case (wstate)
     83 	W_ADDR: if (s.awvalid) begin
     84 			wstate_next = W_DATA;
     85 			wready_next = 1;
     86 			twid_next = s.awid;
     87 			wreg_next = s.awaddr[R_ADDR_WIDTH+1:2];
     88 		end else begin
     89 			awready_next = 1;
     90 		end
     91 	W_DATA: if (s.wvalid) begin
     92 			wstate_next = W_RESP;
     93 			bvalid_next = 1;
     94 		end else begin
     95 			wready_next = 1;
     96 		end
     97 	W_RESP: if (s.bready) begin
     98 			wstate_next = W_ADDR;
     99 			awready_next = 1;
    100 		end else begin
    101 			bvalid_next = 1;
    102 		end
    103 	endcase
    104 end
    105 
    106 typedef enum { R_ADDR, R_CAPTURE, R_CAPTURE2, R_DATA } rstate_t;
    107 
    108 rstate_t rstate = R_ADDR;
    109 rstate_t rstate_next;
    110 
    111 reg arready_next;
    112 reg rvalid_next;
    113 reg rlast_next;
    114 
    115 reg [31:0]rdata = 0;
    116 reg [31:0]rdata_next;
    117 assign s.rdata = rdata;
    118 
    119 reg rd_next;
    120 
    121 reg [`IWIDTH-1:0]trid = 0;
    122 reg [`IWIDTH-1:0]trid_next;
    123 assign s.rid = trid;
    124 
    125 always_comb begin 
    126 	rstate_next = rstate;
    127 	rdata_next = rdata;
    128 	rreg_next = o_rreg;
    129 	trid_next = trid;
    130 	arready_next = 0;
    131 	rvalid_next = 0;
    132 	rlast_next = 0;
    133 	rd_next = 0;
    134 	case (rstate)
    135 	R_ADDR: if (s.arvalid) begin
    136 			// accept address from AXI
    137 			rstate_next = R_CAPTURE;
    138 			trid_next = s.arid;
    139 			rreg_next = s.araddr[R_ADDR_WIDTH+1:2];
    140 			rd_next = 1;
    141 		end else begin
    142 			arready_next = 1;
    143 		end
    144 	R_CAPTURE: begin
    145 			// present address and rd to register file
    146 			rstate_next = R_CAPTURE2;
    147 		end
    148 	R_CAPTURE2: begin
    149 			// capture register file output
    150 			rstate_next = R_DATA;
    151 			rvalid_next = 1;
    152 			rlast_next = 1;
    153 			rdata_next = i_rdata;
    154 		end
    155 	R_DATA: if (s.rready) begin
    156 			// present register data to AXI
    157 			rstate_next = R_ADDR;
    158 			arready_next = 1;
    159 		end else begin
    160 			rvalid_next = 1;
    161 			rlast_next = 1;
    162 		end
    163 	endcase
    164 end
    165 
    166 always_ff @(posedge clk) begin
    167 	wstate <= wstate_next;
    168 	//wdata <= wdata_next;
    169 	twid <= twid_next;
    170 	s.awready <= awready_next;
    171 	s.wready <= wready_next;
    172 	s.bvalid <= bvalid_next;
    173 	o_wreg <= wreg_next;
    174 
    175 	rstate <= rstate_next;
    176 	rdata <= rdata_next;
    177 	trid <= trid_next;
    178 	s.arready <= arready_next;
    179 	s.rvalid <= rvalid_next;
    180 	s.rlast <= rlast_next;
    181 	o_rreg <= rreg_next;
    182 	o_rd <= rd_next;
    183 end
    184 
    185 endmodule