绪论
本项目用Verilog HDL语言设计了AHB总线上的SRAM控制器,SRAM存储器在AHB总线上作为AHB slave存在,该SRAM控制器具有以下特性:
-
支持单周期的SRAM读写操作
-
支持低功耗工作
SRAM存储体由两个Bank组成,系统根据地址选中一块/多块Bank,未被选中的Bank将处于low-power standby模式以降低功耗 -
支持DFT功能
DFT(Design for Test,可测性设计),指通过在芯片原始设计中插入各种用于提高芯片可测试性(包括可控制性和可观测性)的硬件逻辑,从而使芯片变得容易测试,大幅度节省芯片测试的成本。
本项目中,DFT功能通过BIST(Build-in Self Test,内建自测试)实现,采用March C-作为检测算法
最后,在Vivado平台上对本项目进行了逻辑仿真与验证
1. SRAM数据读写功能的实现
1.1 顶层设计架构
下面给出本项目的顶层设计架构,其中sram_top为顶层模块,其下包含sram_interface模块以及SRAM_core两个子模块
sram_interface模块:本质是AHB总线上的slave接口,起到连接总线与SRAM存储体的作用,具体来说:
- 将HCLK,HRESETn,HTRANS,HBURST,HWRITE,HWDATA这些来自于AHB总线的信号转化为存储器接口信号
- 接收存储器8位读数据SRAM_q,并根据总线给出的地址,整理成为32位HRDATA,然后返回给AHB总线
sram_core模块:包含两块32位SRAM存储体Bank,其中每块Bank包含4个8k×8的单端口SRAM,本项目中通过例化Vivado中的IP核生成,实际芯片生产应用中常通过Memory Compiler生成
sram_bist模块:使用SRAM读写功能时,可看做8k×8的单端口SRAM;当BIST功能被使能时,将会由sram_bist内部的内建自测试电路生成Pattern对SRAM进行DFT测试。在本项目中,BIST功能将基于March C-算法设计,具体将在本文的第二章中介绍。在第一章中,我们将每个sram_bist模块视为8k×8的单端口SRAM即可
在上图中标注出了模块的主要信号,其中红色、蓝色的信号分别代表了两个不同的数据通路
红色数据通路:正常使用SRAM读写功能时的信号,interface接收来自于AHB总线的信号,并将其转化为SRAM所需要的控制信号和写数据,然后再由interface将SRAM的读数据整理后返回AHB总线
蓝色数据通路:使用DFT功能时的信号。BIST_en = 1时,DFT功能被使能,此时红色信号全部被屏蔽。该功能用于芯片生产完毕之后,对每块芯片进行DFT测试以检测是否有生产故障,该数据通路对于SRAM的逻辑功能来说,属于冗余的部分,但是在实际芯片生产中却是必不可少的
在本章中,我们关注红色数据通路的电路设计,而DFT功能设计将在第二章中进行介绍
1.2 AHB SRAM读写时序
AHB总线时序:
其中来自AHB总线的control信号包括HTRANS,HBURST,HWRITE
SRAM接口时序:
写时序:
读时序:
读时序与写时序的区别主要在于SRAM_ADDR的处理上:
对于写操作,为了将地址与数据对齐,sram_interface模块会将总线上的地址与控制信号写入寄存器,
而对于读操作,为了实现总线上的单周期读出,会直接将地址送到SRAM端口(注意:SRAM的时钟为AHB总线时钟信号HCLK)。这样,在数据周期刚开始时,读数据就可以返回HRDATA,
这样的设计具有一些局限性:由于SRAM端口上的读地址相比于写地址要滞后一个周期,因此当写操作的下一个周期切换为读操作时,会产生地址冲突,
于是,SRAM控制器会将HREADY拉低一个周期,进行缓冲,下一个周期才会重新拉高HREADY并且返回相应的读数据,
在连续执行多个读操作/连续执行多个写操作时,则不会有这样的问题,可以以AHB总线所允许的最高的速度进行SRAM读写访问,
由于在实际应用中,存储器访问一般不会频繁地在读与写之间切换,因此这样设计对于访问速度带来的代价并不大,
而这样设计的好处,则在于可以避免为SRAM引入额外的时钟源
在明确了AHB SRAM读写的设计需求和读写时序后,我们来看看具体的硬件电路是怎样用Verilog实现的:
1.3 sram_top
首先是顶层模块,主要内容是对两个子模块进行了例化,其中涉及到的信号均已经在架构图中标明,这里不再赘述
module sram_top (
// AHB Signal
input HCLK,
input HRESETn,
input HSEL ,
input [1:0] HTRANS,
input [2:0] HBURST,
input [2:0] HSIZE ,
input HWRITE,
input [15:0] HADDR ,
input [31:0] HWDATA,
output HREADY,
output [1:0] HRESP ,
output [31:0] HRDATA,
// DFT Signal
input BIST_en ,
output BIST_done ,
output BIST_fail
);
// Wires Between SRAM_interface and SRAM_core
wire SRAM_WEN_BANK0;
wire SRAM_WEN_BANK1;
wire [12:0] SRAM_ADDR ;
wire [3:0] SRAM_CSN_BANK0;
wire [3:0] SRAM_CSN_BANK1;
wire [31:0] SRAM_WDATA ;
wire [7:0] SRAM0_q;
wire [7:0] SRAM1_q;
wire [7:0] SRAM2_q;
wire [7:0] SRAM3_q;
wire [7:0] SRAM4_q;
wire [7:0] SRAM5_q;
wire [7:0] SRAM6_q;
wire [7:0] SRAM7_q;
/*————————————————————————————————————————————————————————————————————————*\
/ SRAM Interface Instantiation \
\*————————————————————————————————————————————————————————————————————————*/
sram_interface u_interface(
//---------------AHB SIGNAL--------------
//in
.iHCLK (HCLK ),
.iHRESETn(HRESETn),
.iHSEL (HSEL ),
.iHBURST (HBURST ),
.iHWRITE (HWRITE ),
.iHTRANS (HTRANS ),
.iHSIZE (HSIZE ),
.iHWDATA (HWDATA ),
.iHADDR (HADDR ),
//out
.oHRESP (HRESP ),
.oHREADY (HREADY ),
.oHRDATA (HRDATA ),
//--------------SRAM SIGNAL