最简单的IP核,AXI4_lite GPIO 编写

  GPIO对于相对来说算是最简单的一个功能IP了,就只是单纯的输出0或1,复杂点的就是GPIO的三态输出。不过熟悉GPIO的原理后,用Verilog来实现并不困难,难度点主要是寄存器的分配计算,可能计算起来确实挺麻烦。

  话不多说,直接上代码:

  顶层文件Axi4_Gpio.v,例化了上一篇文章讲到的Axi4_lite_slave.v及接下来的Gpio_ctrl.v模块。

  1 //**************************************************************************
  2 // *** file name    : Axi4_Gpio.v
  3 // *** version      : 1.0
  4 // *** Description  : AXI4-Lite GPIO
  5 // *** Blogs        : https://www.cnblogs.com/WenGalois123/
  6 // *** Author       : Galois_V
  7 // *** Date         : 2022.3.31        
  8 // *** Changes      :       
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module Axi4_Gpio
 12 #(
 13     parameter            IO_NUM = 64
 14 )
 15 (
 16     input        wire                    i_s_axi_aclk            ,
 17     input        wire                    i_s_axi_aresetn         ,
 18     input        wire    [31:0]          i_s_axi_awaddr          ,
 19     input        wire    [2:0]           i_s_axi_awprot          ,
 20     input        wire                    i_s_axi_awvalid         ,
 21     output       wire                    o_s_axi_awready         ,
 22     input        wire    [31:0]          i_s_axi_wdata           ,
 23     input        wire    [3:0]           i_s_axi_wstrb           ,
 24     input        wire                    i_s_axi_wvalid          ,
 25     output       wire                    o_s_axi_wready          ,
 26     output       wire    [1:0]           o_s_axi_bresp           ,
 27     output       wire                    o_s_axi_bvalid          ,
 28     input        wire                    i_s_axi_bready          ,
 29     input        wire    [31:0]          i_s_axi_araddr          ,
 30     input        wire    [2:0]           i_s_axi_arprot          ,
 31     input        wire                    i_s_axi_arvalid         ,
 32     output       wire                    o_s_axi_arready         ,
 33     output       wire    [31:0]          o_s_axi_rdata           ,
 34     output       wire    [1:0]           o_s_axi_rresp           ,
 35     output       wire                    o_s_axi_rvalid          ,
 36     input        wire                    i_s_axi_rready          ,
 37     input                [IO_NUM-1:0]    i_gpio_if_i             ,
 38     output               [IO_NUM-1:0]    o_gpio_if_o             ,
 39     output               [IO_NUM-1:0]    o_gpio_if_t                
 40 );
 41 
 42     wire                [31:0]            w_ctrl_wr_addr         ;
 43     wire                                  w_ctrl_wr_en           ;
 44     wire                [31:0]            w_ctrl_wr_data         ;
 45     wire                [3:0]             w_ctrl_wr_mask         ;
 46     wire                [31:0]            w_ctrl_rd_addr         ;
 47     wire                [31:0]            w_ctrl_rd_data         ;
 48 
 49 /******************************************************************************\
 50 Axi4_lite_slave interface
 51 \******************************************************************************/
 52     Axi4_lite_slave u_Axi4_lite_slave
 53     (
 54         .i_s_axi_aclk              (i_s_axi_aclk              ),
 55         .i_s_axi_aresetn           (i_s_axi_aresetn           ),
 56         .i_s_axi_awaddr            (i_s_axi_awaddr            ),
 57         .i_s_axi_awprot            (i_s_axi_awprot            ),
 58         .i_s_axi_awvalid           (i_s_axi_awvalid           ),
 59         .o_s_axi_awready           (o_s_axi_awready           ),
 60         .i_s_axi_wdata             (i_s_axi_wdata             ),
 61         .i_s_axi_wstrb             (i_s_axi_wstrb             ),
 62         .i_s_axi_wvalid            (i_s_axi_wvalid            ),
 63         .o_s_axi_wready            (o_s_axi_wready            ),
 64         .o_s_axi_bresp             (o_s_axi_bresp             ),
 65         .o_s_axi_bvalid            (o_s_axi_bvalid            ),
 66         .i_s_axi_bready            (i_s_axi_bready            ),
 67         .i_s_axi_araddr            (i_s_axi_araddr            ),
 68         .i_s_axi_arprot            (i_s_axi_arprot            ),
 69         .i_s_axi_arvalid           (i_s_axi_arvalid           ),
 70         .o_s_axi_arready           (o_s_axi_arready           ),
 71         .o_s_axi_rdata             (o_s_axi_rdata             ),
 72         .o_s_axi_rresp             (o_s_axi_rresp             ),
 73         .o_s_axi_rvalid            (o_s_axi_rvalid            ),
 74         .i_s_axi_rready            (i_s_axi_rready            ),
 75         .o_ctrl_wr_addr            (w_ctrl_wr_addr            ),
 76         .o_ctrl_wr_en              (w_ctrl_wr_en              ),
 77         .o_ctrl_wr_data            (w_ctrl_wr_data            ),
 78         .o_ctrl_wr_mask            (w_ctrl_wr_mask            ),
 79         .o_ctrl_rd_addr            (w_ctrl_rd_addr            ),
 80         .i_ctrl_rd_data            (w_ctrl_rd_data            )
 81     );
 82 
 83 /******************************************************************************\
 84 GPIO control 
 85 \******************************************************************************/
 86     Gpio_ctrl
 87     #(
 88         .IO_NUM                  (IO_NUM                    )
 89     )
 90     u_Gpio_ctrl
 91     (
 92         .i_s_axi_aclk            (i_s_axi_aclk              ),
 93         .i_s_axi_aresetn         (i_s_axi_aresetn           ),
 94         .i_ctrl_wr_addr          (w_ctrl_wr_addr            ),
 95         .i_ctrl_wr_en            (w_ctrl_wr_en              ),
 96         .i_ctrl_wr_data          (w_ctrl_wr_data            ),
 97         .i_ctrl_wr_mask          (w_ctrl_wr_mask            ),
 98         .i_ctrl_rd_addr          (w_ctrl_rd_addr            ),
 99         .o_ctrl_rd_data          (w_ctrl_rd_data            ),
100         .i_gpio_if_i             (i_gpio_if_i               ),
101         .o_gpio_if_o             (o_gpio_if_o               ),
102         .o_gpio_if_t             (o_gpio_if_t               )
103     );
104     
105 endmodule

Axi4_lite_slave.v

 

  1 //**************************************************************************
  2 // *** file name   : Axi4_lite_slave.v
  3 // *** version     : 1.0
  4 // *** Description : AXI4-Lite slave interface
  5 // *** Blogs       : https://www.cnblogs.com/WenGalois123/
  6 // *** Author      : Galois_V
  7 // *** Date        : 2022.3.29
  8 // *** Changes     :
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module Axi4_lite_slave
 12 (
 13     input        wire                 i_s_axi_aclk            ,
 14     input        wire                 i_s_axi_aresetn         ,
 15     input        wire    [31:0]       i_s_axi_awaddr          ,
 16     input        wire    [2:0]        i_s_axi_awprot          ,
 17     input        wire                 i_s_axi_awvalid         ,
 18     output       reg                  o_s_axi_awready         ,
 19     input        wire    [31:0]       i_s_axi_wdata           ,
 20     input        wire    [3:0]        i_s_axi_wstrb           ,
 21     input        wire                 i_s_axi_wvalid          ,
 22     output       reg                  o_s_axi_wready          ,
 23     output       wire    [1:0]        o_s_axi_bresp           ,
 24     output       reg                  o_s_axi_bvalid          ,
 25     input        wire                 i_s_axi_bready          ,
 26     input        wire    [31:0]       i_s_axi_araddr          ,
 27     input        wire    [2:0]        i_s_axi_arprot          ,
 28     input        wire                 i_s_axi_arvalid         ,
 29     output       reg                  o_s_axi_arready         ,
 30     output       reg     [31:0]       o_s_axi_rdata           ,
 31     output       wire    [1:0]        o_s_axi_rresp           ,
 32     output       reg                  o_s_axi_rvalid          ,
 33     input        wire                 i_s_axi_rready          ,
 34     output       reg     [31:0]       o_ctrl_wr_addr          ,
 35     output       wire                 o_ctrl_wr_en            ,
 36     output       wire    [31:0]       o_ctrl_wr_data          ,
 37     output       wire    [3:0]        o_ctrl_wr_mask          ,
 38     output       reg     [31:0]       o_ctrl_rd_addr          ,
 39     input        wire    [31:0]       i_ctrl_rd_data
 40 );
 41 
 42     reg                                r_wr_en;
 43     reg                                r_rd_en;
 44     wire                               w_raddr_en;
 45 /******************************************************************************\
 46 Write Address operation
 47 \******************************************************************************/
 48     always@(posedge i_s_axi_aclk)
 49     begin
 50         if(~i_s_axi_aresetn)
 51         begin
 52             r_wr_en <= 1'b1;
 53         end
 54         else if(o_ctrl_wr_en)
 55         begin
 56             r_wr_en <= 1'b0;
 57         end
 58         else if(o_s_axi_bvalid & i_s_axi_bready)
 59         begin
 60             r_wr_en <= 1'b1;
 61         end
 62     end
 63 
 64     always@(posedge i_s_axi_aclk)
 65     begin
 66         if(~i_s_axi_aresetn)
 67         begin
 68             o_s_axi_awready <= 'd0;
 69         end
 70         else if(~o_s_axi_awready & i_s_axi_wvalid & i_s_axi_awvalid & r_wr_en)
 71         begin
 72             o_s_axi_awready <= 1'b1;
 73         end
 74         else
 75         begin
 76             o_s_axi_awready <= 'd0;
 77         end
 78     end
 79 
 80     always@(posedge i_s_axi_aclk)
 81     begin
 82         if(~i_s_axi_aresetn)
 83         begin
 84             o_ctrl_wr_addr <= 'd0;
 85         end
 86         else if(~o_s_axi_awready & i_s_axi_awvalid & i_s_axi_wvalid)
 87         begin
 88             o_ctrl_wr_addr <= i_s_axi_awaddr;
 89         end
 90     end
 91 /******************************************************************************\
 92 Write data operation
 93 \******************************************************************************/
 94     always@(posedge i_s_axi_aclk)
 95     begin
 96         if(~i_s_axi_aresetn)
 97         begin
 98             o_s_axi_wready <= 'd0;
 99         end
100         else if(~o_s_axi_wready & i_s_axi_wvalid & i_s_axi_awvalid & r_wr_en)
101         begin
102             o_s_axi_wready <= 1'b1;
103         end
104         else
105         begin
106             o_s_axi_wready <= 'd0;
107         end
108     end
109 
110     assign o_ctrl_wr_data = i_s_axi_wdata;
111     assign o_ctrl_wr_mask = i_s_axi_wstrb;
112     assign o_ctrl_wr_en = o_s_axi_awready & i_s_axi_awvalid & i_s_axi_wvalid & o_s_axi_wready;
113 
114 /******************************************************************************\
115 write response and response
116 \******************************************************************************/
117     always@(posedge i_s_axi_aclk)
118     begin
119         if(~i_s_axi_aresetn)
120         begin
121             o_s_axi_bvalid <= 'd0;
122         end
123         else if(~o_s_axi_bvalid & o_ctrl_wr_en)
124         begin
125             o_s_axi_bvalid <= 1'b1;
126         end
127         else if(o_s_axi_bvalid & i_s_axi_bready)
128         begin
129             o_s_axi_bvalid <= 'd0;
130         end
131     end
132 
133 /******************************************************************************\
134 Read Address operation
135 \******************************************************************************/
136     always@(posedge i_s_axi_aclk)
137     begin
138         if(~i_s_axi_aresetn)
139         begin
140             r_rd_en <= 1'b1;
141         end
142         else if(w_raddr_en)
143         begin
144             r_rd_en <= 1'b0;
145         end
146         else if(o_s_axi_rvalid & i_s_axi_rready)
147         begin
148             r_rd_en <= 1'b1;
149         end
150     end
151 
152     always@(posedge i_s_axi_aclk)
153     begin
154         if(~i_s_axi_aresetn)
155         begin
156             o_s_axi_arready <= 'd0;
157         end
158         else if(~o_s_axi_arready & i_s_axi_arvalid & r_rd_en)
159         begin
160             o_s_axi_arready <= 1'b1;
161         end
162         else
163         begin
164             o_s_axi_arready <= 'd0;
165         end
166     end
167 
168     always@(posedge i_s_axi_aclk)
169     begin
170         if(~i_s_axi_aresetn)
171         begin
172             o_ctrl_rd_addr <= 'd0;
173         end
174         else if(~o_s_axi_arready & i_s_axi_arvalid)
175         begin
176             o_ctrl_rd_addr <= i_s_axi_araddr;
177         end
178     end
179 
180     assign w_raddr_en = o_s_axi_arready & i_s_axi_arvalid & (~o_s_axi_rvalid);
181 /******************************************************************************\
182 Read data operation
183 \******************************************************************************/
184     always@(posedge i_s_axi_aclk)
185     begin
186         if(~i_s_axi_aresetn)
187         begin
188             o_s_axi_rvalid <= 'd0;
189         end
190         else if(w_raddr_en)
191         begin
192             o_s_axi_rvalid <= 1'b1;
193         end
194         else if(o_s_axi_rvalid & i_s_axi_rready)
195         begin
196             o_s_axi_rvalid <= 'd0;
197         end
198     end
199 
200     always@(posedge i_s_axi_aclk)
201     begin
202         if(~i_s_axi_aresetn)
203         begin
204             o_s_axi_rdata <= 'd0;
205         end
206         else if(w_raddr_en)
207         begin
208             o_s_axi_rdata <= i_ctrl_rd_data;
209         end
210     end
211 
212 
213     assign o_s_axi_rresp = 2'b00;
214     assign o_s_axi_bresp = 2'b00;
215 
216 endmodule
View Code

 

Gpio_ctrl.v

 

  1 //**************************************************************************
  2 // *** file name      : Gpio_ctrl.v
  3 // *** version        : 1.0
  4 // *** Description    : Gpio control
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.3.31        
  8 // *** Changes        :       
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module Gpio_ctrl
 12 #(
 13     parameter            IO_NUM = 512
 14 )
 15 (
 16     input        wire                    i_s_axi_aclk            ,
 17     input        wire                    i_s_axi_aresetn         ,
 18     input        wire    [31:0]          i_ctrl_wr_addr          ,
 19     input        wire                    i_ctrl_wr_en            ,
 20     input        wire    [31:0]          i_ctrl_wr_data          ,
 21     input        wire    [3:0]           i_ctrl_wr_mask          ,
 22     input        wire    [31:0]          i_ctrl_rd_addr          ,
 23     output       reg     [31:0]          o_ctrl_rd_data          ,
 24     input        wire    [IO_NUM-1:0]    i_gpio_if_i             ,
 25     output       reg     [IO_NUM-1:0]    o_gpio_if_o             ,
 26     output       reg     [IO_NUM-1:0]    o_gpio_if_t                
 27 );
 28 
 29 
 30 
 31     parameter                GPIO_CH = IO_NUM / 32;
 32     
 33     
 34     wire                [31:0]    w_gpio_map[3*GPIO_CH:0]        ;
 35     
 36 genvar i;
 37 generate
 38     for(i = 1; i <= GPIO_CH; i = i + 1)
 39     begin
 40         assign w_gpio_map[i-1]                             = o_gpio_if_o[(i*32-1)-:32];
 41         assign w_gpio_map[i + GPIO_CH-1]                 = o_gpio_if_t[(i*32-1)-:32];
 42         assign w_gpio_map[i + GPIO_CH*2-1]                 = i_gpio_if_i[(i*32-1)-:32];
 43 
 44 /******************************************************************************\
 45 GPIO o io registers
 46 \******************************************************************************/        
 47         always@(posedge i_s_axi_aclk)
 48         begin
 49             if(~i_s_axi_aresetn)
 50             begin
 51                 o_gpio_if_o[(i*8-1)-:8] <= 'd0;
 52             end
 53             else if((i_ctrl_wr_addr[7:2] == i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[0])
 54             begin
 55                 o_gpio_if_o[(i*8-1)-:8] <= i_ctrl_wr_data[7:0];
 56             end
 57         end
 58         always@(posedge i_s_axi_aclk)
 59         begin
 60             if(~i_s_axi_aresetn)
 61             begin
 62                 o_gpio_if_o[(i*16-1)-:8] <= 'd0;
 63             end
 64             else if((i_ctrl_wr_addr[7:2] == i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[1])
 65             begin
 66                 o_gpio_if_o[(i*16-1)-:8] <= i_ctrl_wr_data[15:8];
 67             end
 68         end
 69         always@(posedge i_s_axi_aclk)
 70         begin
 71             if(~i_s_axi_aresetn)
 72             begin
 73                 o_gpio_if_o[(i*24-1)-:8] <= 'd0;
 74             end
 75             else if((i_ctrl_wr_addr[7:2] == i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[2])
 76             begin
 77                 o_gpio_if_o[(i*24-1)-:8] <= i_ctrl_wr_data[23:16];
 78             end
 79         end
 80         always@(posedge i_s_axi_aclk)
 81         begin
 82             if(~i_s_axi_aresetn)
 83             begin
 84                 o_gpio_if_o[(i*32-1)-:8] <= 'd0;
 85             end
 86             else if((i_ctrl_wr_addr[7:2] == i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[3])
 87             begin
 88                 o_gpio_if_o[(i*32-1)-:8] <= i_ctrl_wr_data[31:24];
 89             end
 90         end
 91 /******************************************************************************\
 92 GPIO t io registers
 93 \******************************************************************************/
 94         always@(posedge i_s_axi_aclk)
 95         begin
 96             if(~i_s_axi_aresetn)
 97             begin
 98                 o_gpio_if_t[(i*8-1)-:8] <= 'd0;
 99             end
100             else if((i_ctrl_wr_addr[7:2] == GPIO_CH+i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[0])
101             begin
102                 o_gpio_if_t[(i*8-1)-:8] <= i_ctrl_wr_data[7:0];
103             end
104         end
105         always@(posedge i_s_axi_aclk)
106         begin
107             if(~i_s_axi_aresetn)
108             begin
109                 o_gpio_if_t[(i*16-1)-:8] <= 'd0;
110             end
111             else if((i_ctrl_wr_addr[7:2] == GPIO_CH+i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[1])
112             begin
113                 o_gpio_if_t[(i*16-1)-:8] <= i_ctrl_wr_data[15:8];
114             end
115         end
116         always@(posedge i_s_axi_aclk)
117         begin
118             if(~i_s_axi_aresetn)
119             begin
120                 o_gpio_if_t[(i*24-1)-:8] <= 'd0;
121             end
122             else if((i_ctrl_wr_addr[7:2] == GPIO_CH+i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[2])
123             begin
124                 o_gpio_if_t[(i*24-1)-:8] <= i_ctrl_wr_data[23:16];
125             end
126         end
127         always@(posedge i_s_axi_aclk)
128         begin
129             if(~i_s_axi_aresetn)
130             begin
131                 o_gpio_if_t[(i*32-1)-:8] <= 'd0;
132             end
133             else if((i_ctrl_wr_addr[7:2] == GPIO_CH+i-1) & i_ctrl_wr_en & i_ctrl_wr_mask[3])
134             begin
135                 o_gpio_if_t[(i*32-1)-:8] <= i_ctrl_wr_data[31:24];
136             end
137         end
138     end
139 endgenerate
140 /******************************************************************************\
141 GPIO all registers read operation
142 \******************************************************************************/
143     always@(*)
144     begin
145         o_ctrl_rd_data <= w_gpio_map[i_ctrl_rd_addr[7:2]];
146     end
147     
148 endmodule

 

以上便是最简单的AXI4_GPIO的代码,具体寄存器地址根据设置的IO_NUM定。

如果IO_NUM=32:

o_gpio_if_o[31:0]      R/W          0x00

o_gpio_if_t[31:0]       R/W          0x04

i_gpio_if_i[31:0]               R             0x08

 

如果是IO_NUM=64:

 

 

o_gpio_if_o[31:0]      R/W          0x00

o_gpio_if_o[63:32]      R/W          0x04

 

o_gpio_if_t[31:0]       R/W          0x08

o_gpio_if_t[63:32]       R/W          0x0C

 

i_gpio_if_i[31:0]               R            0x10

i_gpio_if_i[63:32]             R            0x14

 

 

可以根据代码计算出相应的寄存器地址,这里的地址是IP核内的,实际地址应该还有前面设备地址高24位,组成的完整地址应该是32bit。

后续将介绍用vivado软件进行对此IP核的封装。

posted on 2022-03-31 13:40  Galois_V  阅读(506)  评论(0编辑  收藏  举报