ahb2apb.v 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. module ahb2apb #(parameter integer
  2. ADDR_BITS = 32,
  3. DATA_BITS = 32
  4. ) (
  5. input reset,
  6. input ahb_clock,
  7. input ahb_hmastlock,
  8. input [1:0] ahb_htrans,
  9. input ahb_hsel,
  10. input ahb_hready,
  11. input ahb_hwrite,
  12. input [ADDR_BITS-1:0] ahb_haddr,
  13. input [2:0] ahb_hsize,
  14. input [2:0] ahb_hburst,
  15. input [3:0] ahb_hprot,
  16. input [DATA_BITS-1:0] ahb_hwdata,
  17. output [DATA_BITS-1:0] ahb_hrdata,
  18. output ahb_hreadyout,
  19. output ahb_hresp,
  20. input apb_clock,
  21. output apb_psel,
  22. output apb_penable,
  23. output apb_pwrite,
  24. output [ADDR_BITS-1:0] apb_paddr,
  25. output [DATA_BITS-1:0] apb_pwdata,
  26. output [3:0] apb_pstrb,
  27. output [2:0] apb_pprot,
  28. input apb_pready,
  29. input apb_pslverr,
  30. input [DATA_BITS-1:0] apb_prdata
  31. );
  32. localparam apbIdle = 2'b00;
  33. localparam apbSetup = 2'b01;
  34. localparam apbAccess = 2'b10;
  35. reg [1:0] apbState;
  36. reg psel;
  37. reg penable;
  38. reg pwrite;
  39. reg [ADDR_BITS-1:0] paddr;
  40. reg [3:0] pstrb;
  41. reg [DATA_BITS-1:0] prdata;
  42. reg pvalid;
  43. reg pdone;
  44. reg [ADDR_BITS-1:0] haddr;
  45. reg hreadyout;
  46. reg hresp;
  47. reg hwrite;
  48. reg [2:0] hsize;
  49. reg hdone;
  50. wire [3:0] ahb_strb = hwrite ? (~(~1'b0 << (1 << hsize)) << haddr[1:0]) : 'b0;
  51. wire apb_pdone = psel && penable && apb_pready;
  52. always @ (posedge ahb_clock or posedge reset) begin
  53. if (reset) begin
  54. hreadyout <= 1'b1;
  55. haddr <= 0;
  56. hwrite <= 1'b0;
  57. hsize <= 3'b0;
  58. end else if (ahb_hsel && ahb_htrans[1] && hreadyout && !hresp) begin
  59. hreadyout <= 1'b0;
  60. haddr <= ahb_haddr;
  61. hwrite <= ahb_hwrite;
  62. hsize <= ahb_hsize;
  63. end else if (pdone && !hdone || hresp) begin
  64. // hdone is used to prevent hreadyout going high due to pdone from previous access
  65. hreadyout <= 1'b1;
  66. end
  67. end
  68. always @ (posedge ahb_clock or posedge reset) begin
  69. if (reset) begin
  70. hdone <= 1'b1;
  71. end else if (hreadyout) begin
  72. hdone <= 1'b1;
  73. end else if (pvalid) begin
  74. hdone <= 1'b0;
  75. end
  76. end
  77. always @ (posedge apb_clock or posedge reset) begin
  78. if (reset) begin
  79. pvalid <= 1'b0;
  80. end else if (!hreadyout && !(psel || pdone)) begin
  81. pvalid <= 1'b1;
  82. end else begin
  83. pvalid <= 1'b0;
  84. end
  85. end
  86. always @ (posedge apb_clock or posedge reset) begin
  87. if (reset) begin
  88. pdone <= 1'b0;
  89. end else if (pdone) begin
  90. pdone <= 1'b0;
  91. end else if (apb_pdone) begin
  92. pdone <= 1'b1;
  93. end
  94. end
  95. always @ (posedge apb_clock or posedge reset) begin
  96. if (reset) begin
  97. apbState <= apbIdle;
  98. psel <= 'b0;
  99. penable <= 'b0;
  100. pwrite <= 'b0;
  101. paddr <= 'h0;
  102. pstrb <= 'h0;
  103. end else begin
  104. case (apbState)
  105. apbIdle: begin // idle => setup
  106. if (pvalid) begin
  107. apbState <= apbSetup;
  108. psel <= 'b1;
  109. pwrite <= hwrite;
  110. paddr <= {haddr[ADDR_BITS-1:2], 2'b00};
  111. pstrb <= ahb_strb;
  112. end
  113. end
  114. apbSetup: begin // setup => access
  115. apbState <= apbAccess;
  116. penable <= 'b1;
  117. end
  118. apbAccess: begin // access => setup or idle
  119. if (apb_pready) begin
  120. if (pvalid) begin // => setup
  121. apbState <= apbSetup;
  122. penable <= 'b0;
  123. psel <= 'b1;
  124. pwrite <= hwrite;
  125. paddr <= {haddr[ADDR_BITS-1:2], 2'b00};
  126. pstrb <= ahb_strb;
  127. end else begin // => idle
  128. apbState <= apbIdle;
  129. penable <= 'b0;
  130. psel <= 'b0;
  131. end
  132. end
  133. end
  134. endcase
  135. end
  136. end
  137. always @ (posedge apb_clock or posedge reset) begin
  138. if (reset) begin
  139. prdata <= 'b0;
  140. end else if (apb_pdone) begin
  141. prdata <= apb_prdata;
  142. end
  143. end
  144. always @ (posedge ahb_clock or posedge reset) begin
  145. if (reset) begin
  146. hresp <= 1'b0;
  147. end else if (ahb_hready) begin
  148. hresp <= 1'b0;
  149. end else if (apb_pdone & apb_pslverr) begin
  150. hresp <= 1'b1;
  151. end
  152. end
  153. assign ahb_hreadyout = hreadyout;
  154. assign ahb_hresp = hresp;
  155. assign ahb_hrdata = prdata;
  156. assign apb_psel = psel;
  157. assign apb_penable = penable;
  158. assign apb_pwrite = pwrite;
  159. assign apb_paddr = paddr;
  160. assign apb_pprot = 3'b001;
  161. assign apb_pwdata = ahb_hwdata;
  162. assign apb_pstrb = pstrb;
  163. endmodule