AMBA APB总线

  前面分析了AHB总线协议。接下来分析APB总线协议。

  (一) APB总线接口:

  PCLK APB总线时钟。

  PRESETn APB总线复位。低有效。

  PADDR 地址总线。

  PSELx 从设备选择。

  PENABLE APB传输选通。

  PWRITE 高为写传输,低为读。

  PRDATA 读数据总线。

  PWDATA 写数据总线。

  接口信号定义如下:

 1 interface   apb_slv_intf #(
 2     parameter   AW  = 32,
 3                 DW  = 32
 4 ) (
 5     input   logic       PCLK,
 6     input   logic       PRESETn
 7 );
 8     logic               PSEL;
 9     logic               PENABLE;
10     logic   [AW-1:0]    PADDR;
11     logic               PWRITE;
12     logic   [DW-1:0]    PWDATA;
13     
14     logic   [DW-1:0]    PRDATA;
15     
16     
17     modport m (
18         input   PRDATA,
19         output  PSEL, PENABLE, PADDR, PWRITE, PWDATA
20     );
21     
22     modport s (
23         input   PSEL, PENABLE, PADDR, PWRITE, PWDATA,
24         output  PRDATA
25     );
26     
27 endinterface: apb_slv_intf

  (二) APB总线时序图:

AMBA APB总线_第1张图片

写传输

AMBA APB总线_第2张图片

读传输

  注意在PENABLE信号有效后从设备需要给出有效数据/读取有效数据。

  (三) AHB总线到APB总线转换桥

  1 module ahb2apb_bridge #(
  2     parameter   AHB_AW  = 32,
  3                 AHB_DW  = 32,
  4                 APB_AW  = 32,
  5                 APB_DW  = 32,
  6                 NSLV    = 16
  7 ) (
  8     input   logic   HCLK,
  9     input   logic   HRESETn,
 10     input   logic   PCLK,
 11     input   logic   PRESETn,
 12     ahb_slv_intf.s  ahb,
 13     apb_slv_intf.m  apbv[NSLV]
 14 );
 15     
 16     logic   ahb_work;
 17     logic   apb_work;
 18     
 19     genvar  i;
 20     
 21     typedef enum logic [1:0] {
 22         AHB_IDLE    = 2'b00,
 23         AHB_WRITE   = 2'b01,
 24         AHB_READ    = 2'b10,
 25         AHB_WAIT    = 2'b11
 26     } ahb_state_e;
 27     
 28     // Signal of AHB Domain
 29     struct {
 30         logic                   work;
 31         logic   [AHB_AW-1:0]    addr;
 32         logic   [AHB_DW-1:0]    data;
 33         logic                   write;
 34         ahb_state_e             cstate, nstate;
 35     } ahbd;
 36     
 37     typedef enum logic [1:0] {
 38         APB_IDLE    = 2'b00,
 39         APB_WRITE   = 2'b01,
 40         APB_READ    = 2'b10
 41     } apb_state_e;
 42     
 43     // Signal of APB Domain
 44     struct {
 45         logic                   work;
 46         logic   [APB_DW-1:0]    data[NSLV];
 47         logic                   PSEL[NSLV];
 48         logic                   PENABLE[NSLV];
 49         apb_state_e             cstate, nstate;
 50     } apbd;
 51     
 52     
 53     // AHB Control Logic
 54     always_comb begin
 55         case (ahbd.cstate)
 56             AHB_IDLE: begin
 57                 if (ahb.HSEL && ahb.HTRANS == HTRANS_NONSEQ) begin
 58                     if (ahb.HWRITE)
 59                         ahbd.nstate = AHB_WRITE;
 60                     else
 61                         ahbd.nstate = AHB_READ;
 62                 end
 63                 else
 64                     ahbd.nstate = AHB_IDLE;
 65             end
 66             AHB_WRITE: begin
 67                 if (apbd.work)
 68                     ahbd.nstate = AHB_WAIT;
 69                 else
 70                     ahbd.nstate = AHB_WRITE;
 71             end 
 72             AHB_READ: begin
 73                 if (apbd.work)
 74                     ahbd.nstate = AHB_WAIT;
 75                 else
 76                     ahbd.nstate = AHB_READ;
 77             end
 78             AHB_WAIT: begin
 79                 if (!apbd.work)
 80                     ahbd.nstate = AHB_IDLE;
 81                 else
 82                     ahbd.nstate = AHB_WAIT;
 83             end
 84             default: ahbd.nstate = AHB_IDLE;
 85         endcase
 86     end
 87     
 88     always_ff @(posedge HCLK or negedge HRESETn) begin
 89         if (!HRESETn)
 90             ahbd.cstate <= AHB_IDLE;
 91         else
 92             ahbd.cstate <= ahbd.nstate;
 93     end
 94     
 95     always_ff @(posedge HCLK or negedge HRESETn) begin
 96         if (!HRESETn) begin
 97             ahbd.work   <= 1'b0;
 98             ahbd.addr   <= '0;
 99             ahbd.data   <= '0;
100             ahbd.write  <= 1'b0;
101             ahb.HREADY  <= 1'b1;
102             ahb.HRDATA[APB_DW-1:0]  <= '0;
103         end
104         else begin
105             case (ahbd.cstate)
106                 AHB_IDLE: begin
107                     if (ahb.HSEL && ahb.HTRANS == HTRANS_NONSEQ) begin
108                         ahbd.addr   <= ahb.HADDR;
109                         ahbd.write  <= ahb.HWRITE;
110                         ahb.HREADY  <= 1'b0;
111                     end
112                     else begin
113                         ahbd.addr   <= '0;
114                         ahbd.write  <= 1'b0;
115                         ahb.HREADY  <= 1'b1;
116                     end
117                     ahbd.work   <= 1'b0;
118                     ahbd.data   <= '0;
119                     ahb.HRDATA[APB_DW-1:0]  <= apbd.data[ahbd.addr[AHB_AW-5:AHB_AW-8]];
120                 end
121                 AHB_WRITE: begin
122                     ahb.HREADY  <= 1'b0;
123                     ahbd.work   <= 1'b1;
124                     ahbd.data   <= ahb.HWDATA;
125                     ahb.HRDATA[APB_DW-1:0]  <= '0;
126                 end
127                 AHB_READ: begin
128                     ahbd.work   <= 1'b1;
129                     ahbd.data   <= '0;
130                     ahb.HREADY  <= 1'b0;
131                     ahb.HRDATA[APB_DW-1:0]  <= '0;
132                 end
133                 AHB_WAIT: begin
134                     ahbd.work   <= 1'b0;
135                     ahb.HREADY  <= 1'b0;
136                     ahb.HRDATA[APB_DW-1:0]  <= '0;
137                 end
138             endcase
139         end
140     end
141     
142     assign  ahb.HRESP = HRESP_OKAY;
143     // assign  ahb.HRDATA[AHB_DW-1:APB_DW] = '0;
144     
145     
146     // APB Control Logic
147     always_comb begin
148         case (apbd.cstate)
149             APB_IDLE: begin
150                 if (ahbd.work) begin
151                     if (ahbd.write)
152                         apbd.nstate = APB_WRITE;
153                     else
154                         apbd.nstate = APB_READ;
155                 end
156                 else
157                     apbd.nstate = APB_IDLE;
158             end
159             APB_WRITE:  apbd.nstate = APB_IDLE;
160             APB_READ:   apbd.nstate = APB_IDLE;
161             default:    apbd.nstate = APB_IDLE;
162         endcase
163     end
164     
165     always_ff @(posedge PCLK or negedge PRESETn) begin
166         if (!PRESETn)
167             apbd.cstate <= APB_IDLE;
168         else
169             apbd.cstate <= apbd.nstate;
170     end
171     
172     always_ff @(posedge PCLK or negedge PRESETn) begin
173         if (!PRESETn) begin
174             apbd.work   <= 1'b0;
175             for (int j = 0; j < NSLV; j++) begin
176                 apbd.PSEL[j]    <= 1'b0;
177                 apbd.PENABLE[j] <= 1'b0;
178             end
179         end
180         else begin
181             case (apbd.cstate)
182                 APB_IDLE: begin
183                     if (ahbd.work) begin
184                         apbd.work <= 1'b1;
185                         for (int j = 0; j < NSLV; j++)
186                             apbd.PSEL[j] <= (ahbd.addr[AHB_AW-5:AHB_AW-8] == j) ? 1'b1 : 1'b0;
187                     end
188                     else begin
189                         apbd.work <= 1'b0;
190                         for (int j = 0; j < NSLV; j++)
191                             apbd.PSEL[j] <= 1'b0;
192                     end
193                     for (int j = 0; j < NSLV; j++)
194                         apbd.PENABLE[j] <= 1'b0;
195                 end
196                 APB_WRITE: begin
197                     apbd.work <= 1'b1;
198                     for (int j = 0; j < NSLV; j++)
199                         apbd.PENABLE[j] <= (ahbd.addr[AHB_AW-5:AHB_AW-8] == j) ? 1'b1 : 1'b0;
200                 end
201                 APB_READ: begin
202                     apbd.work <= 1'b1;
203                     for (int j = 0; j < NSLV; j++)
204                         apbd.PENABLE[j] <= (ahbd.addr[AHB_AW-5:AHB_AW-8] == j) ? 1'b1 : 1'b0;
205                 end
206             endcase
207         end
208     end
209     
210     generate
211         for (i = 0; i < NSLV; i++) begin: apbv_loop
212             assign apbv[i].PADDR    = {4'h0, ahbd.addr[APB_AW-4-1:0]};
213             assign apbv[i].PWRITE   = ahbd.write;
214             assign apbv[i].PWDATA   = ahbd.data[APB_DW-1:0];
215             assign apbd.data[i]     = apbv[i].PRDATA;
216             assign apbv[i].PSEL     = apbd.PSEL[i];
217             assign apbv[i].PENABLE  = apbd.PENABLE[i];
218         end
219     endgenerate
220 
221 endmodule: ahb2apb_bridge

 

你可能感兴趣的:(AMBA APB总线)