IT评测·应用市场-qidao123.com

标题: FPGA项目——基于AMBA总线的流水灯控制系统 [打印本页]

作者: 熊熊出没    时间: 2023-4-4 14:28
标题: FPGA项目——基于AMBA总线的流水灯控制系统
绪论

本文将介绍一个完全用Verilog HDL手写的AMBA片上系统,项目的主题是设计一个基于AMBA总线的流水灯控制系统
项目中所有数字电路逻辑都将通过Verilog进行RTL设计,不会调用成熟IP核,
然后利用Vivado平台对RTL模型进行仿真、综合与布线,最后在FPGA开发板上进行板级验证。

AMBA是ARM公司推出的一种总线架构,目前已非常成熟,在行业内得到广泛的应用,极具实际应用价值,
本项目涉及了AMBA架构中的AHB协议APB协议
系统包括AHB总线、APB总线两个部分,
整个系统的基本架构如下图所示:

总的来说,由AHB总线上的主机————流水灯控制单元(Control Unit),发出控制信号,
进而对APB总线上的从机GPIO模块进行配置,实现对流水灯的流动方式的控制,
本项目是一个完整的AMBA总线系统,包括总线、主机、从机以及外设,
在各章节中,将会介绍如何利用Verilog语言对以下模块进行RTL设计:
1. Control Unit模块
2. AHB2APB Bridge模块
3. GPIO模块
希望本项目能给对AMBA总线架构感兴趣的朋友们一些启发与帮助。
下面,先简要介绍一下AHB/APB总线的基本特性和数据传输时序:
AHB总线协议简介:

AHB总线,全称为Advanced High performance Bus,属于AMBA2.0规范中的一部分,
在SoC片上系统中,AHB主要用于一些高性能模块之间的连接(如CPU、DMA、DSP等),
主要的特性包括:单时钟边沿操作、支持突发传输、支持多个主控制器、可配置总线宽度(32位~128位)、支持字节、半字、字传输。
一个典型的AHB总线系统通常以下图所示的方式进行多主机多从机互联:

可以看出,Master(主机)这边的地址信号HADDR和数据信号HWDATA都是广播的,通过仲裁器arbiter给出的hselx来选择对应的从机,
而Slave(从机)这边的数据,则是通过Decoder来解码给主机这边的。
当HSELx选中对应的从设备后,就可以开始传输了,一个无等待传输的时序如下所示:

图中可以看出,AHB总线具有流水线特性,地址周期和数据周期交替进行
APB总线协议简介:

APB,全称为Advanced Peripheral Bus,主要用于低带宽的周边外设之间的连接,例如UART、1284等,
APB总线架构不像AHB支持多个Master,在APB里面唯一的Master就是APB桥。
APB总线特性包括:
下图展示了APB总线上的一次标准的数据传输时序:

其他有关APB总线的介绍,将在下文AHB2APB Bridge模块的设计章节中涉及
1. 系统架构与功能

系统架构:


本项目的系统架构框图上图所示,
其中,蓝色部分为AHB总线以及AHB上的主机从机,粉色部分则是APB总线以及APB上的主机从机,
下面介绍一下总线上各个模块的功能和定义:
项目中涉及到的外设在开发板上的位置如下图所示:

流水灯系统工作模式:


2.  AHB2APB Bridge模块设计

首先介绍AHB2APB Bridge模块的设计方法,
该模块是AHB与APB总线之间的桥梁,负责两种协议信号的相互转换,
AHB2APB Bridge的模块框图和信号定义如下:

AHB2APB Bridge既是AHB总线上的一个Slave,也作为APB总线上唯一的Master,
其任务是将来自于AHB总线上的信号转化为APB信号,实现AHB系统和APB的互联,
那么如何实现一个可以完成上述功能的Bridge模块呢?
答案是通过一个有限状态机(FSM,Finite State Machine)来进行控制,
看看一次典型的AHB到APB信号转换时序图(以Read为例):

在T1-T2期间,Bridge作为AHB总线上的Slave被HADDR选中,
在T2-T4两个时钟周期内,Bridge将AHB的HADDR上的地址Addr1放在APB总线的PADDR上,
其中T2-T3,PENABLE尚未被拉高,且HREADY会被Bridge拉低,因为APB的传输速度是低于AHB的,需要AHB总线上的Master进行等待,
而T3-T4,PENABLE被Bridge使能,数据信息被放上PRDATA并且由Bridge转交给HRDATA,
我们将T1-T2,T2-T3,T3-T4这个周期分别称为IDLESETUPENABLE
于是我们得到AHB2APB Bridge的状态机转换示意图:

注意:在T2-T4传输Data1后,APB总线又在T4-T6两个周期内完成了Data2的传输,
这两次传输之间并没有经历IDLE状态,这表明当AHB总线上仍然有传输任务时,ENABLE状态结束后会直接再次跳往SETUP状态以准备下一个数据的传输,
AHB2APB Bridge模块完整RTL如下:
  1. module AHB2APB_bridge #(
  2.     //HRANS Parameters
  3.     parameter    IDLE   = 2'b00  ,
  4.     parameter    BUSY   = 2'b01  ,
  5.     parameter    SEQ    = 2'b10  ,
  6.     parameter    NONSEQ = 2'b11  ,
  7.     //HRSP Parameters
  8.     parameter    OKAY  = 2'b00   ,
  9.     parameter    ERROR = 2'b01   ,
  10.     parameter    SPLIT = 2'b10   ,
  11.     parameter    RETRY = 2'b11   ,
  12.     //bridge_state Parameters
  13.     parameter    BRIDGE_IDLE   = 2'b00,
  14.     parameter    BRIDGE_SETUP  = 2'b01,
  15.     parameter    BRIDGE_ENABLE = 2'b10,
  16.     //ADDR Parameters
  17.     parameter    ADDR_GPIO_0   = 32'h0000_0000,
  18.     parameter    ADDR_GPIO_1   = 32'h0000_8000
  19.    
  20. ) (
  21.     //------------ AHB ------------
  22.     //input
  23.     input iHCLK,
  24.     input iHRESETn,
  25.     input iHSEL,
  26.     input  [1:0]  iHTRANS,
  27.     input  [3:0]  iHSIZE ,
  28.     input  [2:0]  iHBURST,
  29.     input         iHWRITE,
  30.     input  [31:0] iHWDATA,
  31.     input  [31:0] iHADDR ,
  32.     //output
  33.     output        oHREADY,
  34.     output [1:0]  oHRESP ,
  35.     output [31:0] oHRDATA,
  36.     //------------ APB ------------
  37.     //input
  38.     input [31:0] iPRDATA,
  39.     //output
  40.     output oPSEL0,
  41.     output oPSEL1,
  42.     output oPWRITE,
  43.     output oPENABLE,
  44.     output [31:0] oPADDR,
  45.     output [31:0] oPWDATA
  46. );
  47.     /*————————————————————————————————————————————————————————————————————————*\
  48.     /                            AHB Signal Register                           \
  49.     \*————————————————————————————————————————————————————————————————————————*/
  50.     reg         iHWRITE_r ;
  51.     reg  [31:0] iHADDR_r  ;
  52.     reg  [31:0] iHWDATA_r ;
  53.     always@( posedge iHCLK)  begin
  54.         if(!iHRESETn) begin
  55.             iHWRITE_r <= 1'b0;
  56.             iHADDR_r  <= 32'b0;
  57.             iHWDATA_r <= 32'b0;
  58.         end
  59.         else if( iHSEL && (bridge_state == BRIDGE_IDLE || bridge_state == BRIDGE_ENABLE))begin
  60.             iHWRITE_r <= iHWRITE; // ahb reg change when bridge_state is going to change:
  61.             iHADDR_r  <= iHADDR ; // from IDLE   to SETUP                     
  62.             iHWDATA_r <= iHWDATA; // from ENABLE to SETUP
  63.         end
  64.     end
  65.     /*————————————————————————————————————————————————————————————————————————*\
  66.     /                                 Bridge FSM                               \
  67.     \*————————————————————————————————————————————————————————————————————————*/
  68.     reg [1:0] bridge_state;
  69.     always @(posedge iHCLK ) begin
  70.         if (!iHRESETn) begin
  71.             bridge_state <= BRIDGE_IDLE;
  72.         end else begin
  73.             case ( bridge_state )
  74.                 // IDLE
  75.                 BRIDGE_IDLE: begin
  76.                     if(iHSEL) begin
  77.                         bridge_state <= BRIDGE_SETUP;
  78.                     end
  79.                     else begin
  80.                         bridge_state <= BRIDGE_IDLE;
  81.                     end                     
  82.                 end
  83.                 // SETUP
  84.                 BRIDGE_SETUP: begin
  85.                     bridge_state <= BRIDGE_ENABLE;
  86.                 end
  87.                 // ENABLE
  88.                 BRIDGE_ENABLE: begin
  89.                     if(iHSEL) begin
  90.                         bridge_state <= BRIDGE_SETUP;
  91.                     end
  92.                     else begin
  93.                         bridge_state <= BRIDGE_IDLE;
  94.                     end
  95.                 end
  96.                 //DEFAULT
  97.                 default: bridge_state <= BRIDGE_IDLE;
  98.             endcase
  99.         end
  100.     end
  101.     /*————————————————————————————————————————————————————————————————————————*\
  102.     /                               AHB Slave Output                           \
  103.     \*————————————————————————————————————————————————————————————————————————*/
  104.     assign oHREADY = ( bridge_state == BRIDGE_SETUP ) ? 1'b0 : 1'b1;
  105.     assign oHRESP  = OKAY ;
  106.     assign oHRDATA = iPRDATA;
  107.     /*————————————————————————————————————————————————————————————————————————*\
  108.     /                               APB Master Output                          \
  109.     \*————————————————————————————————————————————————————————————————————————*/
  110.     assign oPSEL0   = ( iHADDR_r == ADDR_GPIO_0) ? 1'b1 : 1'b0;
  111.     assign oPSEL1   = ( iHADDR_r == ADDR_GPIO_1) ? 1'b1 : 1'b0;
  112.     assign oPWRITE  = iHWRITE_r ;
  113.     assign oPENABLE = ( bridge_state == BRIDGE_ENABLE ) ? 1'b1 : 1'b0;
  114.     assign oPADDR   = iHADDR_r;
  115.     assign oPWDATA  = iHWDATA_r;
  116. endmodule
复制代码
最后是呼吸灯模式(工作模式3),
该模式相对复杂一些,前面提到过是通过改变占空比控制LED灯亮度的,
占空比的改变是通过对timer的判断实现的,
举个例子:
  1.     reg [31:0] oGPIOout ;
  2.     always @(*) begin
  3.         for ( i=0 ; i<32 ; i=i+1 ) begin
  4.             if( reg_DIRM[i] & reg_OEN[i] ) begin //output mode
  5.                 oGPIOout[i] = reg_DATA[i] ;
  6.             end else begin
  7.                 oGPIOout[i] = 1'bz;
  8.             end
  9.         end
  10.     end
复制代码
(timer[1:0] == 2'b00 )的判定,在timer的值每增加4的过程中,必定出现且只出现1次
这样在 (timer >= 32'd89_999_999 )的这段期间内,
LED灯的驱动引脚就会在25%的时间里处于低电平(点亮),剩下的75%时间里处于高电平(熄灭),
同理,(timer[2:0] == 3'b0 )就能得到1/8的占空比,也就是12.5%,
这样就有:
  1.             for ( i=0 ; i<32 ; i=i+1 ) begin
  2.                 if ( reg_DIRM[i] ) begin
  3.                     reg_DATA_RO[i] <= oGPIOout[i] ;// output mode
  4.                 end else begin
  5.                     reg_DATA_RO[i] <= iGPIOin[i] ;// input mode      
  6.                 end  
  7.             end  
复制代码
可以看出上述代码实现了占空比从0% → 1.56% → 3.12% → 6.25% → 12.5% → 25% → 12.5% → 6.25% → 3.12% → 1.56% → 0%的等时间间隔变化,
由于开发板LED灯功率较高,在25%到100%之间的占空比,LED灯亮度都会很高,看不出太大变化,
因此我们将25%设定为了最高的占空比,对应LED灯最亮的时刻。
至此,Control Unit的设计就介绍完了,下面我们将演示系统在FPGA开发板上的实际运行视频
5. FPGA验证

本项目所用开发板型号:XC7A35T-2FGG484I
上板验证视频:
(视频制作中,录制完会第一时间更新视频链接)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4