| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- module ahb2apb #(parameter integer
- ADDR_BITS = 32,
- DATA_BITS = 32
- ) (
- input reset,
- input ahb_clock,
- input ahb_hmastlock,
- input [1:0] ahb_htrans,
- input ahb_hsel,
- input ahb_hready,
- input ahb_hwrite,
- input [ADDR_BITS-1:0] ahb_haddr,
- input [2:0] ahb_hsize,
- input [2:0] ahb_hburst,
- input [3:0] ahb_hprot,
- input [DATA_BITS-1:0] ahb_hwdata,
- output [DATA_BITS-1:0] ahb_hrdata,
- output ahb_hreadyout,
- output ahb_hresp,
- input apb_clock,
- output apb_psel,
- output apb_penable,
- output apb_pwrite,
- output [ADDR_BITS-1:0] apb_paddr,
- output [DATA_BITS-1:0] apb_pwdata,
- output [3:0] apb_pstrb,
- output [2:0] apb_pprot,
- input apb_pready,
- input apb_pslverr,
- input [DATA_BITS-1:0] apb_prdata
- );
- localparam apbIdle = 2'b00;
- localparam apbSetup = 2'b01;
- localparam apbAccess = 2'b10;
- reg [1:0] apbState;
- reg psel;
- reg penable;
- reg pwrite;
- reg [ADDR_BITS-1:0] paddr;
- reg [3:0] pstrb;
- reg [DATA_BITS-1:0] prdata;
- reg pvalid;
- reg pdone;
- reg [ADDR_BITS-1:0] haddr;
- reg hreadyout;
- reg hresp;
- reg hwrite;
- reg [2:0] hsize;
- reg hdone;
- wire [3:0] ahb_strb = hwrite ? (~(~1'b0 << (1 << hsize)) << haddr[1:0]) : 'b0;
- wire apb_pdone = psel && penable && apb_pready;
- always @ (posedge ahb_clock or posedge reset) begin
- if (reset) begin
- hreadyout <= 1'b1;
- haddr <= 0;
- hwrite <= 1'b0;
- hsize <= 3'b0;
- end else if (ahb_hsel && ahb_htrans[1] && hreadyout && !hresp) begin
- hreadyout <= 1'b0;
- haddr <= ahb_haddr;
- hwrite <= ahb_hwrite;
- hsize <= ahb_hsize;
- end else if (pdone && !hdone || hresp) begin
- // hdone is used to prevent hreadyout going high due to pdone from previous access
- hreadyout <= 1'b1;
- end
- end
- always @ (posedge ahb_clock or posedge reset) begin
- if (reset) begin
- hdone <= 1'b1;
- end else if (hreadyout) begin
- hdone <= 1'b1;
- end else if (pvalid) begin
- hdone <= 1'b0;
- end
- end
- always @ (posedge apb_clock or posedge reset) begin
- if (reset) begin
- pvalid <= 1'b0;
- end else if (!hreadyout && !(psel || pdone)) begin
- pvalid <= 1'b1;
- end else begin
- pvalid <= 1'b0;
- end
- end
- always @ (posedge apb_clock or posedge reset) begin
- if (reset) begin
- pdone <= 1'b0;
- end else if (pdone) begin
- pdone <= 1'b0;
- end else if (apb_pdone) begin
- pdone <= 1'b1;
- end
- end
- always @ (posedge apb_clock or posedge reset) begin
- if (reset) begin
- apbState <= apbIdle;
- psel <= 'b0;
- penable <= 'b0;
- pwrite <= 'b0;
- paddr <= 'h0;
- pstrb <= 'h0;
- end else begin
- case (apbState)
- apbIdle: begin // idle => setup
- if (pvalid) begin
- apbState <= apbSetup;
- psel <= 'b1;
- pwrite <= hwrite;
- paddr <= {haddr[ADDR_BITS-1:2], 2'b00};
- pstrb <= ahb_strb;
- end
- end
- apbSetup: begin // setup => access
- apbState <= apbAccess;
- penable <= 'b1;
- end
- apbAccess: begin // access => setup or idle
- if (apb_pready) begin
- if (pvalid) begin // => setup
- apbState <= apbSetup;
- penable <= 'b0;
- psel <= 'b1;
- pwrite <= hwrite;
- paddr <= {haddr[ADDR_BITS-1:2], 2'b00};
- pstrb <= ahb_strb;
- end else begin // => idle
- apbState <= apbIdle;
- penable <= 'b0;
- psel <= 'b0;
- end
- end
- end
- endcase
- end
- end
- always @ (posedge apb_clock or posedge reset) begin
- if (reset) begin
- prdata <= 'b0;
- end else if (apb_pdone) begin
- prdata <= apb_prdata;
- end
- end
- always @ (posedge ahb_clock or posedge reset) begin
- if (reset) begin
- hresp <= 1'b0;
- end else if (ahb_hready) begin
- hresp <= 1'b0;
- end else if (apb_pdone & apb_pslverr) begin
- hresp <= 1'b1;
- end
- end
- assign ahb_hreadyout = hreadyout;
- assign ahb_hresp = hresp;
- assign ahb_hrdata = prdata;
- assign apb_psel = psel;
- assign apb_penable = penable;
- assign apb_pwrite = pwrite;
- assign apb_paddr = paddr;
- assign apb_pprot = 3'b001;
- assign apb_pwdata = ahb_hwdata;
- assign apb_pstrb = pstrb;
- endmodule
|