设为首页 加入收藏

TOP

「FPGA项目」—— 基于AMBA总线的流水灯控制系统(五)
2023-07-23 13:25:06 】 浏览:314
Tags:FPGA 项目 基于 AMBA 水灯控
gt; DATA_RO -> PRADATA assign oPRDATA = reg_DATA_RO; // reg_DATA -> GPIOout reg [31:0] oGPIOout ; always @(*) begin for ( i=0 ; i<32 ; i=i+1 ) begin if( reg_DIRM[i] & reg_OEN[i] ) begin //output mode oGPIOout[i] = reg_DATA[i] ; end else begin oGPIOout[i] = 1'bz; end end end endmodule

4. Control Unit(流水灯控制单元)模块设计

4.1 有限状态机设计

我们的AMBA流水灯控制系统的核心:Control Unit,即控制单元,

Bridge模块是APB上所有外设的Master,而CU模块则是Bridge在AHB上的Master,

可以说是Master中的Master了,

Control Unit是信号传输的发起者,决定总线上是在读还是在写、也决定访问的从机是哪个,

CU发出的控制信号包括HTRANS、HBURST、HSIZE、HADDR,数据信号包括HWDATA,

这些AHB信号如何生成均是由Control Unit负责的,

同时CU也需要接收HRDATA,并对其进行解读判断,

那么这些AHB信号是如何生成的呢?

实际上,Control Unit模块也是通过一个有限状态机实现的:

下面介绍一下该FSM的各个状态所代表的含义:

1. CONFIG_0~2:按下复位按钮/上电后,对GPIO外设进行初始化配置,

其中,CONFIG_0
将GPIO的0~3位引脚配置为输入模式,连接FPGA开发板的Key按键进行观测
将GPIO的4~7位引脚配置为输出模式,连接FPGA开发板的LED灯进行驱动控制

CONFIG_1
将GPIO的4~7位引脚的输出电平均设定为高电平1(本开发板上的LED为共阳极,引脚高电平=LED灯熄灭)

CONFIG_2
对GPIO的4~7位引脚进行输出使能

2. READ_DATA_RO
读GPIO的DATA_RO寄存器,根据寄存器[3:0]的值得知Key状态,
该状态是FSM的核心状态,
当配置完GPIO的DIRM、OEN、DATA寄存器后,
我们会开始反复进行读DATA_RO,即观测KEY的状态,
然后根据KEY的值得到对应的LED_mode,
随后会由该状态跳向WRITE_DATA_0~3,对DATA寄存器进行配置,控制LED灯点亮or熄灭

3. WRITE_DATA_0~3
配置不同的流水灯灯工作模式,模式由KEY状态决定,
按下KEY1进入工作模式0,按下KEY2进入工作模式1,按下KEY3进入工作模式2,按下KEY4进入工作模式3,
在初始静止状态下,只有同时按下KEY0~3才能进入工作模式0,
此时按下某个单独的KEY不会有任何反应的

随着FSM状态的改变,CU模块将会给AHB总线发出不同的读写命令,从而实现对GPIO模块的寄存器配置,

下表具体地整理了FSM状态CU模块生成的AHB信号之间的对应关系:

上述FSM状态转换逻辑所对应的RTL:

reg [2:0] CU_state;

    always @(posedge iHCLK ) begin
    if ( !iHRESETn ) begin
        CU_state <= CONFIG_0;
    end else begin
        case (CU_state)
            // write GPIO_DIRM 
            CONFIG_0: begin
                if ( iHREADY ) begin
                    CU_state <= CONFIG_1;
                end else begin
                    CU_state <= CONFIG_0;
                end
            end
            // write GPIO_DATA
            CONFIG_1: begin
                if ( iHREADY ) begin
                    CU_state <= CONFIG_2;
                end else begin
                    CU_state <= CONFIG_1;
                end
            end 
            // write GPIO_OEN 
            CONFIG_2: begin
                if ( iHREADY && iHRDATA[3:0] == 4'b0000) begin
                    CU_state <= READ_DATA_RO;
                end else begin
                    CU_state <= CONFIG_2;
                end
            end 
            // read DATA_RO
            READ_DATA_RO: begin
                if ( iHREADY          && iHRDATA[3:0] == 4'b1110) begin //key1 pressed
                    CU_state <= WRITE_DATA_0;
                end else if ( iHREADY && iHRDATA[3:0] == 4'b1101) begin //key2 pressed
                    CU_state <= WRITE_DATA_1;
                end else if ( iHREADY && iHRDATA[3:0] == 4'b1011) begin //key3 pressed
                    CU_state <= WRITE_DATA_2;
                end else if ( iHREADY && iHRDATA[3:0] == 4'b0111) begin //key4 pressed
                    CU_state <= WRITE_DATA_3;
                end else if ( iHREADY && led_mode[0] )            begin //keep mode0 if not pressed this moment
                    CU_state <= WRITE_DATA_0;             
                end else if ( iHREADY && led_mode[1] )            begin //keep mode1
                    CU_state <= WRITE_DATA_0;             
                end else if ( iHREADY && led_mode[2] )            begin //keep mode2 
                    CU_state <= WRITE_DATA_1;             
                end else if ( iHREADY && led_mode[3] )            begin //keep mode3
                    CU_state <= WRITE_DATA_2;             
                end else begin
                    CU_state <= READ_DATA_RO;     // Slave not ready || no key ever been pressed
                end                             
            end 
            // write DATA
            WRITE_DATA_0 : begin
                if ( iHREADY ) begin
                    CU_state <= READ_DATA_RO;
                end else begin
                    CU_state <= CU_state;
                end
            end 
            // write DATA
            WRITE_DATA_1 : begin
                if ( iHREADY ) begin
                    CU_state <= READ_DATA_RO;
                end else begin
                    CU_state <= CU_state;
                end
            end 
            // write DATA
            WRITE_DATA_2 : begin
                if ( iHREADY ) begin
                    CU_state <= READ_DATA_RO;
                end else begin
                    CU_state <
首页 上一页 2 3 4 5 6 7 8 下一页 尾页 5/10/10
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ZYNQ基于DMA的串口传图 下一篇数字分频器设计(偶数分频、奇数..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目