zynq-sandbox

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

axi_to_reg_impl.sv (4762B)


      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_to_reg_impl (
     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[0:COUNT-1],
     39 	output wire [31:0]o_wdata,
     40 	output wire o_rd[0:COUNT-1],
     41 	output wire o_wr[0:COUNT-1]
     42 	);
     43 
     44 parameter integer COUNT = 8;
     45 
     46 parameter integer R_ADDR_WIDTH = 2;
     47 
     48 `define IWIDTH $bits(s.awid)
     49 
     50 typedef enum { W_ADDR, W_DATA, W_RESP } wstate_t;
     51 
     52 assign s.bresp = 0;
     53 assign s.rresp = 0;
     54 
     55 //reg [31:0]wdata = 0;
     56 //reg [31:0]wdata_next;
     57 
     58 wstate_t wstate = W_ADDR;
     59 wstate_t wstate_next;
     60 
     61 reg awready_next;
     62 reg wready_next;
     63 reg bvalid_next;
     64 
     65 reg [R_ADDR_WIDTH-1:0]wreg_next;
     66 reg [R_ADDR_WIDTH-1:0]rreg_next;
     67 
     68 assign o_wdata = s.wdata;
     69 wire do_wr = (s.wvalid & s.wready);
     70 reg do_rd = 0;
     71 
     72 reg [`IWIDTH-1:0]twid = 0;
     73 reg [`IWIDTH-1:0]twid_next;
     74 
     75 assign s.bid = twid;
     76 
     77 reg [2:0]rsel = 0;
     78 reg [2:0]rsel_next;
     79 reg [2:0]wsel = 0;
     80 reg [2:0]wsel_next;
     81 
     82 reg [7:0]wselbits;
     83 reg [7:0]rselbits;
     84 
     85 decoder3to8 wsel_decoder(
     86 	.in(wsel),
     87 	.out(wselbits)
     88 	);
     89 
     90 decoder3to8 rsel_decoder(
     91 	.in(rsel),
     92 	.out(rselbits)
     93 	);
     94 
     95 generate
     96 for (genvar i = 0; i < COUNT; i++) begin: stuff
     97 	assign o_rd[i] = do_rd & rselbits[i];
     98 	assign o_wr[i] = do_wr & wselbits[i];
     99 end
    100 endgenerate
    101 
    102 always_comb begin
    103 	wstate_next = wstate;
    104 	//wdata_next = wdata;
    105 	wreg_next = o_wreg;
    106 	wsel_next = wsel;
    107 	twid_next = twid;
    108 	awready_next = 0;
    109 	wready_next = 0;
    110 	bvalid_next = 0;
    111 	case (wstate)
    112 	W_ADDR: if (s.awvalid) begin
    113 			wstate_next = W_DATA;
    114 			wready_next = 1;
    115 			twid_next = s.awid;
    116 			wreg_next = s.awaddr[R_ADDR_WIDTH+1:2];
    117 			wsel_next = s.awaddr[22:20];
    118 		end else begin
    119 			awready_next = 1;
    120 		end
    121 	W_DATA: if (s.wvalid) begin
    122 			wstate_next = W_RESP;
    123 			bvalid_next = 1;
    124 		end else begin
    125 			wready_next = 1;
    126 		end
    127 	W_RESP: if (s.bready) begin
    128 			wstate_next = W_ADDR;
    129 			awready_next = 1;
    130 		end else begin
    131 			bvalid_next = 1;
    132 		end
    133 	endcase
    134 end
    135 
    136 typedef enum { R_ADDR, R_CAPTURE, R_CAPTURE2, R_DATA } rstate_t;
    137 
    138 rstate_t rstate = R_ADDR;
    139 rstate_t rstate_next;
    140 
    141 reg arready_next;
    142 reg rvalid_next;
    143 reg rlast_next;
    144 
    145 reg [31:0]rdata = 0;
    146 reg [31:0]rdata_next;
    147 assign s.rdata = rdata;
    148 
    149 reg rd_next;
    150 
    151 reg [`IWIDTH-1:0]trid = 0;
    152 reg [`IWIDTH-1:0]trid_next;
    153 assign s.rid = trid;
    154 
    155 always_comb begin 
    156 	rstate_next = rstate;
    157 	rdata_next = rdata;
    158 	rreg_next = o_rreg;
    159 	rsel_next = rsel;
    160 	trid_next = trid;
    161 	arready_next = 0;
    162 	rvalid_next = 0;
    163 	rlast_next = 0;
    164 	rd_next = 0;
    165 	case (rstate)
    166 	R_ADDR: if (s.arvalid) begin
    167 			// accept address from AXI
    168 			rstate_next = R_CAPTURE;
    169 			trid_next = s.arid;
    170 			rreg_next = s.araddr[R_ADDR_WIDTH+1:2];
    171 			rsel_next = s.araddr[22:20];
    172 			rd_next = 1;
    173 		end else begin
    174 			arready_next = 1;
    175 		end
    176 	R_CAPTURE: begin
    177 			// present address and rd to register file
    178 			rstate_next = R_CAPTURE2;
    179 		end
    180 	R_CAPTURE2: begin
    181 			// capture register file output
    182 			rstate_next = R_DATA;
    183 			rvalid_next = 1;
    184 			rlast_next = 1;
    185 			rdata_next = i_rdata[rsel];
    186 		end
    187 	R_DATA: if (s.rready) begin
    188 			// present register data to AXI
    189 			rstate_next = R_ADDR;
    190 			arready_next = 1;
    191 		end else begin
    192 			rvalid_next = 1;
    193 			rlast_next = 1;
    194 		end
    195 	endcase
    196 end
    197 
    198 always_ff @(posedge clk) begin
    199 	wstate <= wstate_next;
    200 	wsel <= wsel_next;
    201 	//wdata <= wdata_next;
    202 	twid <= twid_next;
    203 	s.awready <= awready_next;
    204 	s.wready <= wready_next;
    205 	s.bvalid <= bvalid_next;
    206 	o_wreg <= wreg_next;
    207 
    208 	rstate <= rstate_next;
    209 	rdata <= rdata_next;
    210 	rsel <= rsel_next;
    211 	trid <= trid_next;
    212 	s.arready <= arready_next;
    213 	s.rvalid <= rvalid_next;
    214 	s.rlast <= rlast_next;
    215 	o_rreg <= rreg_next;
    216 	do_rd <= rd_next;
    217 end
    218 
    219 endmodule
    220 
    221 module decoder3to8(
    222 	input [2:0]in,
    223 	output reg [7:0]out
    224 	);
    225 
    226 always_comb case(in)
    227 	0: out = 8'b00000001;
    228 	1: out = 8'b00000010;
    229 	2: out = 8'b00000100;
    230 	3: out = 8'b00001000;
    231 	4: out = 8'b00010000;
    232 	5: out = 8'b00100000;
    233 	6: out = 8'b01000000;
    234 	7: out = 8'b10000000;
    235 endcase
    236 
    237 endmodule