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