一、团队介绍
我们的队伍名称是我要吃火锅,报名编号为CICC2882。
二、设计思路
DMA模块主要是完成数据的搬运工作,其中它与总线有两个接口,一个是与CPU进行通信,一个是与内存进行通信。与CPU通信的总线接口DMA作为从机,CPU通过对DMA的寄存器进行读写来控制DMA的状态。与内存通信的总线接口DMA作为主机,发出命令信号从SRAM中读或者写数据。
所以DMA模块主要有两个部分,一个是与CPU通信的部分,另一个是与SRAM通信的部分。与CPU通信的部分的ICB时序较为简单,收到命令后可直接与其握手。另一个部分是与SRAM通信,由于DMA中有FIFO,FIFO的时序也影响这ICB总线时序,所以需要整体考虑。
除了ICB时序部分,再添加一个FIFO,以及进行相应的寄存器维护就能使DMA正常工作了。
三、RTL代码分析
(一)寄存器配置ICB时序
1、dma_cfg_icb_cmd_ready
如果是读寄存器的值,则需要等待rsp_valid信号为0时才能读,此时表示没有对寄存器进行写值,如果是写寄存器时,当dma_cfg_icb_cmd_valid产生时则立即将ready拉高。
2、
dma_cfg_icb_rsp_valid
当cmd信号握手后,表明写或者读寄存器值正常,则可以在下一个周期将该信号拉高,直到与rsp信号握手,将这个值拉低。
3、
dma_cfg_icb_rsp_rdata
可以利用组合逻辑实现,但本次模块中采用握手后的下一个周期读出寄存器的值。并且当rsp_valid信号没有拉低时(也就是握手还没有成功时),rdata的值需要一直保持,握手成功后根据寄存器地址进行赋值。
(三)寄存器维护
维护的寄存器如下表
寄存器名称 |
寄存器功能 |
读写 |
地址 |
S_reg |
存放搬运起始地址 |
可读可写 |
0’h00 |
D_reg |
存放搬运目的地址 |
可读可写 |
0’h04 |
Data_len_reg |
存放搬运长度 |
可读可写 |
0’h08 |
CR |
CR[7]:产生开始/再开始命令 CR[0]:中断应答,置1时清除等待的中断 |
可读可写 |
0’h0d |
CTR |
CTR[7]:置1时表示DMA功能使能,软件能够配置命令寄存器来发起命令操作 CTR[6]:中断使能 |
可读可写 |
0’h0e |
SR |
状态寄存器 SR[0]:中断标志 SR[1]:1表示正在传输数据,0表示传输完成 SR[2]:1表示DMA忙状态 SR[3]:1表示寄存器配置已经完成 |
只读 |
0’h0c |
1.
状态寄存器中的中断标志:irq_flag
当DMA工作结束并且CR寄存器中中断应答置为0时,该信号拉高。
2.
整个DMA的中断标志
当状态寄存器中的中断标志为1,并且DMA模块中断使能为1时,可以中断。
(五)FIFO模块
1、读与写地址
初始地址都为0,当空的时候无法进行读操作,满的时候无法进行写操作。
2、空、满与溢出信号
当地址的低5位相同,并且最高位不同时,则表示FIFO已经满了,当读写指针所有位都相同时,则表示FIFO为空。
溢出信号是当FIFO满的时候,还要继续写进数据时,指示的信号,所以可以利用时序逻辑
3、读数据与写数据
读数据与写数据根据读写使能信号以及空满信号,将指针对应的数据读出或者写入。
4、sub_full
由于时序逻辑的延迟,导致状态机在判断下一个状态时要提前知道fifo是否满了,由于fifo的full信号比next_state信号晚两个周期,所以需要一个sub_full信号来指示fifo是否即将满了。
(六)DMA的数据传输
1、传输阶段状态机的实现
在传输阶段,主要有三个状态:初始状态,读SRAM状态,写SRAM状态。
初始状态:当DMA使能信号为0时或者开始信号未拉高时,初始状态下一状态一直未初始状态,表示DMA还未开始传输。
读SRAM状态:当DMA使能信号为0时,其下一状态为初始状态。
当FIFO还没有满,并且读的数据数目还没有达到要求的数目,下一状态继续读。
否则下一个状态为写。
写SRAM状态:当DMA使能信号为0时,其下一状态为初始状态。
当FIFO还未空,并且写的数据数目没有达到要求的数目,下一个状态继续写。
如果读的数据还没读完,则下一个状态变为读。
否则下一个状态变为初始状态。
1、dma_busy
当dma在读或者写状态时,dma为忙状态,但是由于为时序逻辑,会在下一个周期改变值,所以用next_state作为判断依据。
2、dma_done
当写进SRAM的中的data数达到要求的数时,则dma工作结束。
3、w_data
当从机发来rsp信号与主机握手时,将传来的数据赋值给要写进FIFO的数据,为组合逻辑。
(七) ICB访存时序
1、read_cmd_cnt
该always块用来计数发出了多少次访问SRAM的命令,当为读状态时,每cmd握手一次就加一。Write_cmd_cnt、write_rsp_cnt、read_rsp_cnt同理
2、dma_icb_cmd_valid
每握手一次需要拉低一次,由于从机的ready信号不知道何时来,所以不能持续拉高,进行连续的读或者写。
当为读状态,如果读的命令还没有超过需要读的数,则发出命令。
当为写状态,如果写的命令还没有超过需要写的数,则可发出命令。
否则该信号不变。
注意这里不需要考虑从机还没有发出rsp_valid信号主机就再次发出cmd_valid信号了,就算发出了它们也不能握手成功,则该信号就会保持。
3、dma_icb_cmd_addr
注意为组合逻辑,当cmd握手后时,如果为读状态,则地址为s_reg中地址加上偏移量
如果为写状态,则为d_reg中的地址加偏移量。其中偏移量用发出的读或者写命令的次数代替。
1、寄存器地址定义
根据rtl中定义的寄存器地址进行定义
2、中断清除函数
通过对CR寄存器写入值对存在的中断进行清除。
3、DMA初始化
对CTR寄存器写值,对DMA模块使能。
4、数据搬移函数
首先对源地址寄存器,目的地址寄存器,搬移数据长度寄存器分别进行配置,每配置一个寄存器后,不断读状态寄存器的值,当寄存器配置好后则进行下一个寄存器的配置。
当寄存器配置好后,开始搬运数据,直到状态寄存器指示DMA工作已经结束
5、主函数