axi_hub.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. hub_size = 6
  2. source = """
  3. `timescale 1 ns / 1 ps
  4. module axi_hub #
  5. (
  6. parameter integer CFG_DATA_WIDTH = 1024,
  7. parameter integer STS_DATA_WIDTH = 1024
  8. )
  9. (
  10. input wire aclk,
  11. input wire aresetn,
  12. input wire [11:0] s_axi_awid,
  13. input wire [31:0] s_axi_awaddr,
  14. input wire s_axi_awvalid,
  15. output wire s_axi_awready,
  16. input wire [3:0] s_axi_wstrb,
  17. input wire s_axi_wlast,
  18. input wire [31:0] s_axi_wdata,
  19. input wire s_axi_wvalid,
  20. output wire s_axi_wready,
  21. output wire [11:0] s_axi_bid,
  22. output wire s_axi_bvalid,
  23. input wire s_axi_bready,
  24. input wire [11:0] s_axi_arid,
  25. input wire [3:0] s_axi_arlen,
  26. input wire [31:0] s_axi_araddr,
  27. input wire s_axi_arvalid,
  28. output wire s_axi_arready,
  29. output wire [11:0] s_axi_rid,
  30. output wire s_axi_rlast,
  31. output wire [31:0] s_axi_rdata,
  32. output wire s_axi_rvalid,
  33. input wire s_axi_rready,
  34. output wire [CFG_DATA_WIDTH-1:0] cfg_data,
  35. input wire [STS_DATA_WIDTH-1:0] sts_data,
  36. {% for i in range(hub_size) -%}
  37. {% set index = "%02d" % i %}
  38. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram CLK" *)
  39. output wire b{{index}}_bram_clk,
  40. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram RST" *)
  41. output wire b{{index}}_bram_rst,
  42. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram EN" *)
  43. output wire b{{index}}_bram_en,
  44. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram WE" *)
  45. output wire [3:0] b{{index}}_bram_we,
  46. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram ADDR" *)
  47. output wire [21:0] b{{index}}_bram_addr,
  48. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram DIN" *)
  49. output wire [31:0] b{{index}}_bram_wdata,
  50. (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram DOUT" *)
  51. input wire [31:0] b{{index}}_bram_rdata,
  52. input wire [31:0] s{{index}}_axis_tdata,
  53. input wire s{{index}}_axis_tvalid,
  54. output wire s{{index}}_axis_tready,
  55. output wire [31:0] m{{index}}_axis_tdata,
  56. output wire m{{index}}_axis_tvalid,
  57. input wire m{{index}}_axis_tready{% if not loop.last %},{% endif %}
  58. {% endfor -%}
  59. );
  60. localparam integer HUB_SIZE = {{hub_size}};
  61. localparam integer MUX_SIZE = HUB_SIZE + 2;
  62. localparam integer CFG_SIZE = CFG_DATA_WIDTH / 32;
  63. localparam integer CFG_WIDTH = CFG_SIZE > 1 ? $clog2(CFG_SIZE) : 1;
  64. localparam integer STS_SIZE = STS_DATA_WIDTH / 32;
  65. localparam integer STS_WIDTH = STS_SIZE > 1 ? $clog2(STS_SIZE) : 1;
  66. reg [3:0] int_awcntr_reg = 4'd0;
  67. reg [3:0] int_arcntr_reg = 4'd0;
  68. wire int_awvalid_wire, int_awready_wire;
  69. wire int_wvalid_wire, int_wready_wire;
  70. wire int_bvalid_wire, int_bready_wire;
  71. wire int_arvalid_wire, int_arready_wire;
  72. wire int_rvalid_wire, int_rready_wire;
  73. wire [11:0] int_awid_wire;
  74. wire [31:0] int_awaddr_wire;
  75. wire [3:0] int_wstrb_wire;
  76. wire int_wlast_wire;
  77. wire [31:0] int_wdata_wire;
  78. wire [11:0] int_arid_wire;
  79. wire [3:0] int_arlen_wire;
  80. wire [31:0] int_araddr_wire;
  81. wire [11:0] int_rid_wire;
  82. wire int_rlast_wire;
  83. wire [31:0] int_rdata_wire [MUX_SIZE-1:0];
  84. wire [31:0] int_sdata_wire [HUB_SIZE-1:0];
  85. wire [31:0] int_mdata_wire [HUB_SIZE-1:0];
  86. wire [HUB_SIZE-1:0] int_svalid_wire, int_sready_wire;
  87. wire [HUB_SIZE-1:0] int_mvalid_wire, int_mready_wire;
  88. wire [31:0] int_bdata_wire [HUB_SIZE-1:0];
  89. wire [21:0] int_waddr_wire;
  90. wire [21:0] int_raddr_wire;
  91. wire [31:0] int_cfg_mux [CFG_SIZE-1:0];
  92. wire [31:0] int_sts_mux [STS_SIZE-1:0];
  93. wire [31:0] int_rdata_mux [MUX_SIZE-1:0];
  94. wire [MUX_SIZE-1:0] int_wsel_wire, int_rsel_wire;
  95. wire [HUB_SIZE-1:0] int_bsel_wire;
  96. wire [CFG_SIZE-1:0] int_ce_wire;
  97. wire int_we_wire, int_re_wire;
  98. genvar j, k;
  99. assign int_awready_wire = int_bready_wire & int_wvalid_wire & int_wlast_wire;
  100. assign int_wready_wire = int_bready_wire & int_awvalid_wire;
  101. assign int_bvalid_wire = int_awvalid_wire & int_wvalid_wire & int_wlast_wire;
  102. assign int_arready_wire = int_rready_wire & int_rlast_wire;
  103. assign int_rvalid_wire = int_arvalid_wire;
  104. assign int_rlast_wire = int_arcntr_reg == int_arlen_wire;
  105. assign int_we_wire = int_bready_wire & int_awvalid_wire & int_wvalid_wire;
  106. assign int_re_wire = int_rready_wire & int_arvalid_wire;
  107. assign int_waddr_wire = int_awaddr_wire[23:2] + int_awcntr_reg;
  108. assign int_raddr_wire = int_araddr_wire[23:2] + int_arcntr_reg;
  109. assign int_rdata_wire[0] = int_rdata_mux[int_araddr_wire[27:24]];
  110. assign int_rdata_mux[0] = int_cfg_mux[int_raddr_wire[CFG_WIDTH-1:0]];
  111. assign int_rdata_mux[1] = int_sts_mux[int_raddr_wire[STS_WIDTH-1:0]];
  112. generate
  113. for(j = 0; j < HUB_SIZE; j = j + 1)
  114. begin : MUXES
  115. assign int_rdata_mux[j+2] = int_svalid_wire[j] ? int_sdata_wire[j] : 32'd0;
  116. assign int_rdata_wire[j+2] = int_bsel_wire[j] ? int_bdata_wire[j] : 32'd0;
  117. assign int_mdata_wire[j] = int_wdata_wire;
  118. assign int_mvalid_wire[j] = int_wsel_wire[j+2];
  119. assign int_sready_wire[j] = int_rsel_wire[j+2];
  120. end
  121. endgenerate
  122. generate
  123. for(j = 0; j < MUX_SIZE; j = j + 1)
  124. begin : SELECTS
  125. assign int_wsel_wire[j] = int_we_wire & (int_awaddr_wire[27:24] == j);
  126. assign int_rsel_wire[j] = int_re_wire & (int_araddr_wire[27:24] == j);
  127. end
  128. endgenerate
  129. generate
  130. for(j = 0; j < CFG_SIZE; j = j + 1)
  131. begin : CFG_WORDS
  132. assign int_cfg_mux[j] = cfg_data[j*32+31:j*32];
  133. assign int_ce_wire[j] = int_wsel_wire[0] & (int_waddr_wire[CFG_WIDTH-1:0] == j);
  134. for(k = 0; k < 32; k = k + 1)
  135. begin : CFG_BITS
  136. FDRE #(
  137. .INIT(1'b0)
  138. ) FDRE_inst (
  139. .CE(int_ce_wire[j] & int_wstrb_wire[k/8]),
  140. .C(aclk),
  141. .R(~aresetn),
  142. .D(int_wdata_wire[k]),
  143. .Q(cfg_data[j*32 + k])
  144. );
  145. end
  146. end
  147. endgenerate
  148. generate
  149. for(j = 0; j < STS_SIZE; j = j + 1)
  150. begin : STS_WORDS
  151. assign int_sts_mux[j] = sts_data[j*32+31:j*32];
  152. end
  153. endgenerate
  154. always @(posedge aclk)
  155. begin
  156. if(~aresetn | (int_awvalid_wire & int_awready_wire))
  157. begin
  158. int_awcntr_reg <= 4'd0;
  159. end
  160. else if(~int_wlast_wire & int_we_wire)
  161. begin
  162. int_awcntr_reg <= int_awcntr_reg + 1'b1;
  163. end
  164. if(~aresetn | (int_arvalid_wire & int_arready_wire))
  165. begin
  166. int_arcntr_reg <= 4'd0;
  167. end
  168. else if(~int_rlast_wire & int_re_wire)
  169. begin
  170. int_arcntr_reg <= int_arcntr_reg + 1'b1;
  171. end
  172. end
  173. inout_buffer #(
  174. .DATA_WIDTH(44)
  175. ) buf_0 (
  176. .aclk(aclk), .aresetn(aresetn),
  177. .in_data({s_axi_awid, s_axi_awaddr}),
  178. .in_valid(s_axi_awvalid), .in_ready(s_axi_awready),
  179. .out_data({int_awid_wire, int_awaddr_wire}),
  180. .out_valid(int_awvalid_wire), .out_ready(int_awready_wire)
  181. );
  182. inout_buffer #(
  183. .DATA_WIDTH(37)
  184. ) buf_1 (
  185. .aclk(aclk), .aresetn(aresetn),
  186. .in_data({s_axi_wstrb, s_axi_wlast, s_axi_wdata}),
  187. .in_valid(s_axi_wvalid), .in_ready(s_axi_wready),
  188. .out_data({int_wstrb_wire, int_wlast_wire, int_wdata_wire}),
  189. .out_valid(int_wvalid_wire), .out_ready(int_wready_wire)
  190. );
  191. output_buffer #(
  192. .DATA_WIDTH(12)
  193. ) buf_2 (
  194. .aclk(aclk), .aresetn(aresetn),
  195. .in_data(int_awid_wire), .in_valid(int_bvalid_wire), .in_ready(int_bready_wire),
  196. .out_data(s_axi_bid), .out_valid(s_axi_bvalid), .out_ready(s_axi_bready)
  197. );
  198. inout_buffer #(
  199. .DATA_WIDTH(48)
  200. ) buf_3 (
  201. .aclk(aclk), .aresetn(aresetn),
  202. .in_data({s_axi_arid, s_axi_arlen, s_axi_araddr}),
  203. .in_valid(s_axi_arvalid), .in_ready(s_axi_arready),
  204. .out_data({int_arid_wire, int_arlen_wire, int_araddr_wire}),
  205. .out_valid(int_arvalid_wire), .out_ready(int_arready_wire)
  206. );
  207. output_buffer #(
  208. .DATA_WIDTH(HUB_SIZE + 45)
  209. ) buf_4 (
  210. .aclk(aclk), .aresetn(aresetn),
  211. .in_data({int_rsel_wire[MUX_SIZE-1:2] & ~int_svalid_wire, int_arid_wire, int_rlast_wire, int_rdata_wire[0]}),
  212. .in_valid(int_rvalid_wire), .in_ready(int_rready_wire),
  213. .out_data({int_bsel_wire, s_axi_rid, s_axi_rlast, int_rdata_wire[1]}),
  214. .out_valid(s_axi_rvalid), .out_ready(s_axi_rready)
  215. );
  216. assign s_axi_rdata = {{s_axi_rdata(hub_size)}};
  217. {% for i in range(hub_size) -%}
  218. {% set index = "%02d" % i %}
  219. assign int_bdata_wire[{{i}}] = b{{index}}_bram_rdata;
  220. assign b{{index}}_bram_clk = aclk;
  221. assign b{{index}}_bram_rst = ~aresetn;
  222. assign b{{index}}_bram_en = int_rsel_wire[{{i+2}}] | int_wsel_wire[{{i+2}}];
  223. assign b{{index}}_bram_we = int_wsel_wire[{{i+2}}] ? int_wstrb_wire : 4'd0;
  224. assign b{{index}}_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
  225. assign b{{index}}_bram_wdata = int_wdata_wire;
  226. assign int_sdata_wire[{{i}}] = s{{index}}_axis_tdata;
  227. assign int_svalid_wire[{{i}}] = s{{index}}_axis_tvalid;
  228. assign s{{index}}_axis_tready = int_sready_wire[{{i}}];
  229. inout_buffer #(
  230. .DATA_WIDTH(32)
  231. ) mbuf_{{i}} (
  232. .aclk(aclk), .aresetn(aresetn),
  233. .in_data(int_mdata_wire[{{i}}]), .in_valid(int_mvalid_wire[{{i}}]), .in_ready(int_mready_wire[{{i}}]),
  234. .out_data(m{{index}}_axis_tdata), .out_valid(m{{index}}_axis_tvalid), .out_ready(m{{index}}_axis_tready)
  235. );
  236. {% endfor %}
  237. endmodule
  238. """
  239. import jinja2
  240. def s_axi_rdata(n):
  241. return " | ".join(map(lambda i: "int_rdata_wire[%d]" % i, range(1, n + 2)))
  242. print(jinja2.Template(source).render(hub_size=hub_size, s_axi_rdata=s_axi_rdata))