GPIO的源码分成三个部分,分别是ahb_gpio.v, ahb_to_iop.v, iop_gpio.v
对应的是顶层模块,ahb模块和io模块。 顶层模块只对后面两个模块进行了例化和连接。
ahb_to_iop
module cmsdk_ahb_to_iop
// ----------------------------------------------------------------------------
// Port Definitions
// ----------------------------------------------------------------------------
(// AHB Inputs
input wire HCLK, // system bus clock
input wire HRESETn, // system bus reset
input wire HSEL, // AHB peripheral select
input wire HREADY, // AHB ready input
input wire [1:0] HTRANS, // AHB transfer type
input wire [2:0] HSIZE, // AHB hsize
input wire HWRITE, // AHB hwrite
input wire [11:0] HADDR, // AHB address bus
input wire [31:0] HWDATA, // AHB write data bus
// IOP Inputs
input wire [31:0] IORDATA, // I/0 read data bus
// AHB Outputs
output wire HREADYOUT, // AHB ready output to S->M mux
output wire HRESP, // AHB response
output wire [31:0] HRDATA,
// IOP Outputs
output reg IOSEL, // Decode for peripheral
output reg [11:0] IOADDR, // I/O transfer address
output reg IOWRITE, // I/O transfer direction
output reg [1:0] IOSIZE, // I/O transfer size
output reg IOTRANS, // I/O transaction
output wire [31:0] IOWDATA); // I/O write data bus
// ----------------------------------------------------------
// Read/write control logic
// ----------------------------------------------------------
// registered HSEL, update only if selected to reduce toggling
always @(posedge HCLK or negedge HRESETn)
begin
if (~HRESETn)
IOSEL <= 1'b0;
else
IOSEL <= HSEL & HREADY;
end
// registered address, update only if selected to reduce toggling
always @(posedge HCLK or negedge HRESETn)
begin
if (~HRESETn)
IOADDR <= {12{1'b0}};
else
IOADDR <= HADDR[11:0];
end
// Data phase write control
always @(posedge HCLK or negedge HRESETn)
begin
if (~HRESETn)
IOWRITE <= 1'b0;
else
IOWRITE <= HWRITE;
end
// registered hsize, update only if selected to reduce toggling
always @(posedge HCLK or negedge HRESETn)
begin
if (~HRESETn)
IOSIZE <= {2{1'b0}};
else
IOSIZE <= HSIZE[1:0];
end
// registered HTRANS, update only if selected to reduce toggling
always @(posedge HCLK or negedge HRESETn)
begin
if (~HRESETn)
IOTRANS <= 1'b0;
else
IOTRANS <= HTRANS[1];
end
assign IOWDATA = HWDATA;
assign HRDATA = IORDATA;
assign HREADYOUT = 1'b1;
assign HRESP = 1'b0;
endmodule
使用always在HCLK上升沿采样更新
- IOSEL <= HSEL & HREADY
- IOADDR <= HADDR
- IOWRITE <= HWRITE
- IOSIZE <= HSIZE[1:0] 将允许传输的数据大小限制在8bit-64bit
- IOTRANS <= HTRANS[1] 只识别是传输还是不是传输,不考虑NONSEQ与SEQ的区别,不考虑BUSY和IDLE的区别