基于AHB的SRAM设计
一、描述
- 作为系统的缓存;
- SRAM存储体由MeMery complier生成;
- 项目完成SRAM控制器的设计;
- SRAM作为AHB Slave的形式存在;
二、特性
- 支持8位,16位和32位的SRAM数据读写操作;
- 支持SRAM的单周期读写;
- 支持低功耗工作;
- 支持DFT/BIST的功能;
三、基础知识介绍
AMBA:Advanced Microcontroller Bus Architecture高级微控制器总线架构。
AMBA 2.0
定义了三种总线:
AHB(Advanced High-performance Bus):高性能总线;
ASB(Advanced System Bus):高级系统总线(基本不用);
APB(Advanced Peripheral Bus):外围设备总线;
- AHB:
高速总线,高性能;
二级流水线操作;
可支持多个总线主设备(最多16个);
支持burst传输;
总线带宽:8/16/32/64/128bits;
上升沿触发操作;
对于一个新设计建议使用AHB; - APB
低速总线,低功耗;
接口简单;
再Bridge中锁存地址信号和控制信号;
适用于多种外设;
上升沿触发;
1、AHB的介绍
-
AHB的组成
AHB主设备(Master):初始化一次读/写操作;某一时刻只允许一个主设备使用总线。CPU,DMA,DSP,LCDC…
AHB从设备(Slave):响应一次读/写操作;通过地址映射来选择使用哪一个从设备;外部存储器控制器EMI,APB bridge。
AHB总裁器(Arbiter):允许某一个主设备控制总线;再AMBA协议中没有定义仲裁算法。
AHB译码器(Decoder):通过地址译码来决定选择哪一个设备。 -
AHB的基本信号
HRESETN:低电平有效。
HADDR[31:0]:32位系统地址总线。
HWDATA[31:0]:写数据总线,从主设备写到从设备。
HRADTA[31:0]:读数据总线,从从设备读到主设备。
HTRANS:指出当前传输的状态。
HSIZE:指出当前传输的大小。
HBURST:指出传输的burst类型。
HRESP:从设备发给主设备的总线传输状态。
HREADY:高代表从设备指出传输结束;低代表从设备需延长传输周期。
传输类型:HTRANS[1:0]:当前传输状态
00:IDLE --主设备占用总线,但没进行传输;两次burst传输中间主设备发IDLE。
01:BUSY --主设备占用总线,但是再burst传输过程中还没有准备好进行下一次传输;一次burst传输中间主设备发BUSY。
10:NONSEQ --表明一次单个数据的传输;或者一次burst传输的第一个数据;地址和控制信号与上一次传输无关。
11:SEQ --表明burst传输接下来的数据;地址和上一次传输的地址是相关的。
猝发传输类型HBURST:SINGLE,INCR
burst传输不可跨越1k边界。
HSEL:由AHB decoder通过地址映射给出
AHB Slave响应信号:
HREADY传输完成:HRESP传输响应(OK,ERROR,RETRY)
AHB slave短时间无法响应:HREADY拉低。
AHB slave长时间无法响应:发送RETRY信号。
地址译码:
HSELx:选择从设备,指出由主设备所选择的从设备。
由地址译码器提供的选择信号。
记:arbiter用来选择master,decoder用来选择slave
从设备响应:
所访问的从设备必须响应这次传输
从设备可能返回的响应:
- 完成这次传输
- 插入等待状态(HREADY信号)
- 发出错误信号表示这次传输失败
- 延迟传输,使得总线可用于其他传输(split)
HREADY:tranfer done
HRESP[1:0]:tranfer respone
00:OKEY (成功) -单周期响应
01:ERROR(失败) -两周期响应
10:RETRY(传输未完成;请求主设备重新开始一个传输) -两周期响应
11:SPLIT(传输未完成;请求主设备分离一次传输) -两周期响应
总线的流水特性需要从设备两个周期的响应,可以设得从设备有足够的时间处理下一次传输。
BIST:Build In Self Test 内建自测试
DFT(生产过程中):Design for Test 机台芯片测试
SRAM :英文全称是’Static RAM’,Static Random Access Memory的缩写,翻译成中文就是’静态随机存储器’。SRAM主要用于制造Cache。
四、项目
该项目分成三个模块:一个顶层模块sram_top.v;把两个内部模块实例并连接。
两个内部模块为:
- sram_slave_if.v 总线控制单元------------需要我们设计的模块
- sram_core.v 由MeMory Compilier生成
该项目为64k的sram,分成8片8k的sram,每4片组成一个bank:bank0和bank1。
1.sram_top.v
module sramc_top(
//input signals
input wire hclk,
input wire sram_clk,
input wire hresetn,
input wire hsel,
input wire hwrite,
input wire hready,
input wire [2:0] hsize ,
input wire [2:0] hburst,
input wire [1:0] htrans,
input wire [31:0] hwdata,
input wire [31:0] haddr,
//Signals for BIST and DFT test mode
//When signal"dft_en" or "bist_en" is high, sram controller enters into test mode
input wire dft_en,
input wire bist_en,
//output signals
output wire hready_resp,
output wire [1:0] hresp,
output wire [31:0] hrdata,
//When "bist_done" is high, it shows BIST test is over.
output wire bist_done,
//"bist_fail" shows the results of each sram funtions.There are 8 srams in this controller.
output wire [7:0] bist_fail
);
//Select one of the two sram blocks according to the value of sram_csn
wire bank_sel ;
wire [3:0] bank0_csn;
wire [3:0] bank1_csn;
//Each of 8 srams is 8kx8, the depth is 2^13 (8K), so the sram's address width is 13 bits.
wire [12:0] sram_addr;
//AHB bus data write into srams
wire [31:0] sram_wdata;
//sram data output data which selected and read by AHB bus
wire [7:0] sram_q0;
wire [7:0] sram_q1;
wire [7:0] sram_q2;
wire [7:0] sram_q3;
wire [7:0] sram_q4;
wire [7:0] sram_q5;
wire [7:0] sram_q6;
wire [7:0] sram_q7;
// Instance the two modules:
// ahb_slave_if.v and sram_core.v
ahb_slave_if ahb_slave_if_u(
//-----------------------------------------
// AHB input signals into sram controller
//-----------------------------------------
.hclk (hclk),
.hresetn (hresetn),
.hsel (hsel),
.hwrite (hwrite),
.hready (hready),
.hsize (hsize),
.htrans (htrans),
.hburst (hburst),
.hwdata (hwdata),
.haddr (haddr),
//-----------------------------------------
//8 sram blcoks data output into ahb slave interface
//-----------------------------------------
.sram_q0 (sram_q0),
.sram_q1 (sram_q1),
.sram_q2 (sram_q2),
.sram_q3 (sram_q3),
.sram_q4 (sram_q4),
.sram_q5 (sram_q5),
.sram_q6 (sram_q6),
.sram_q7 (sram_q7),
//---------------------------------------------
//AHB slave(sram controller) output signals
//---------------------------------------------
.hready_resp (hready_resp),
.hresp (hresp),
.hrdata (hrdata),
//---------------------------------------------
//sram control signals and sram address
//---------------------------------------------
.sram_w_en (sram_w_en),
.sram_addr_out(sram_addr),
//data write into sram
.sram_wdata (sram_wdata),
//choose the corresponding sram in a bank, active low
.bank_sel (bank_sel ),
.bank0_csn (bank0_csn),
.bank1_csn (bank1_csn)
);
sram_core sram_core_u(
//AHB bus signals
.hclk (hclk ),
.sram_clk (sram_clk),
.hresetn (hresetn ),
//-------------------------------------------
//sram control singals from ahb_slave_if.v
//-------------------------------------------
.sram_addr (sram_addr ),
.sram_wdata_in(sram_wdata),
.sram_wen (sram_w_en ),
.bank_sel (bank_sel ),
.bank0_csn (bank0_csn ),
.bank1_csn (bank1_csn ),
//test mode enable signals
.bist_en (bist_en ),
.dft_en (dft_en ),
//-------------------------------------------
//8 srams data output into AHB bus
//-------------------------------------------
.sram_q0 (sram_q0),
.sram_q1 (sram_q1),
.sram_q2 (sram_q2),
.sram_q3 (sram_q3),
.sram_q4 (sram_q4),
.sram_q5 (sram_q5),
.sram_q6 (sram_q6),
.sram_q7 (sram_q7),
//test results output when in test mode
.bist_done (bist_done),
.bist_fail (bist_fail)
);
endmodule
2.ahb_slave_if.v
该模块位接口模块,将AHB master发送的存取指令转为sram的数据存取与块,片选指令。
module ahb_slave_if(
//input signals
hclk,
hresetn,
hsel,
hwrite,
hready,
hsize,
htrans,
hburst,
hwdata,
haddr,
sram_q0,
sram_q1,
sram_q2,
sram_q3,
sram_q4,
sram_q5,
sram_q6,
sram_q7,
//output signals
hready_resp,
hresp,
hrdata,
sram_w_en,
sram_addr_out,
sram_wdata,
bank0_csn,
bank1_csn
);
//-------------------------------------------------------
list of AHB signals
//-------------------------------------------------------
signals used during normal operation
input hclk;
input hresetn;
//-------------------------------------------------------
signals from AHB bus used during normal operation
//-------------------------------------------------------
input hsel;
input hwrite;
input hready; //=1代表读/写有效
input [2:0] hsize; //用来设置每一次数据传输的大小
input [2:0] hburst;
input [1:0] htrans; //判断当前传输状态
input [31:0] hwdata;
inout [31:0] haddr;
//signals from sram core data output(read srams)
input [7:0] sram_q0;
input [7:0] sram_q1;
input [7:0] sram_q2;
input [7:0] sram_q3;
input [7:0] sram_q4;
input [7:0] sram_q5;
input [7:0] sram_q6;
input [7:0] sram_q7;
//signals tp AHB bus used during normal operation
output hready_resp;
output [1:0] hresp;
output [31:0] hrdata;
//sram read or write enable signals
//when "sram_w_en" is low, it means write sram; and high, it means read sram
output sram_w_en;
//choose the right srams when bank is confirmed:
//bank_csn allows the four bytes in the 32-bit width to be written independently
output [3:0] bank0_csn;
output [3:0] bank1_csn;
//--------------------------------------------------------
//signals to sram core in normal operation ,it contains
//sram address and data writing into sram.
//--------------------------------------------------------
output [12:0] sram_addr_out;
output [31:0] sram_wdata;
//--------------------------------------------------------
//internal registers used for temp the input ahb signals
//--------------------------------------------------------
//temperate all the AHB input signals
reg hwrite_r;
reg [2:0] hsize_r;
reg [2:0] hburst_r;
reg [1:0] htrans_r;
reg [31:0] haddr_r;
reg [3:0] sram_csn;
//-------------------------------------------------
//Internal signals
//-------------------------------------------------
//"haddr_sel" and "hsize_sel" used to generate banks of
//sram: "bank0_sel" and "bank1_sel". wire [1:0] haddr_sel;
wire [1:0] hsize_sel;
wire bank_sel;
wire sram_csn_en; //sram chip select enable
wire sram_write; //sram write enable signal from AHB bus
wire sram_read; //sram read enable signal from AHB bus
wire [15:0] sram_addr; //sram addrss from AHB bus
wire [31:0] sram_data_out; //data read from sram and send to AHB bus
//-------------------------------------------------
//transfer type signal encoding
//-------------------------------------------------
// 用来判断当前传输状态,对应htrans中的4种状态
parameter IDLE = 2'b00,
BUSY = 2'b01,
NONSEQ = 2'b10,
SEQ = 2'b11;
//-------------------------------------------------
//Main code
//-------------------------------------------------
//-------------------------------------------------
//combinatorial portion
//-------------------------------------------------
//assign the response and read data of the ahb slave
//In order to implement the sram function-writing or reading
//in one cycle, the value of hready_resp is always "1"
assign hready_resp = 1'b1;
//响应始终设置为okay
assign hresp = 2'b00;
//----------------------------------------------------
//sram data output to AHB bus
//----------------------------------------------------
assign hrdata = sram_data_out;
//choose the right data output of the two banks(bank0,bank1) according
//to the value of bank_sel. If bank_sel=1'b1,bank0 selected,or bank1 selected.
//通过判断选择哪个bank,将bank中的数据输出
assign sram_data_out = bank_sel?(sram_q3,sram_q2,sram_q1,sram_q0):(sram_q7,sram_q6,sram_q5,sram_q4);
//Generate sram write and read enable signals
// 对sram操作,需要将地址打拍,与数据对应,实现单周期读写
assign sram_write = ((htrants_r == NONSEQ) || (htrans_r == SEQ)) && hwrite_r;
assign sram_read = ((htrants_r == NONSEQ) || (htrans_r == SEQ)) && (!hwrite_r);
// sram的读写使能,1:读 0:写
assign sram_w_en = !sram_write;
//generate sram address
assign sram_addr = haddr_r[15:0];
assign sram_addr_out = sram_addr[14:2];
//generate bank select signals by the values of sram_addr[15].
//each bank(32*32) comprises of four sram block(8k*8),and
//the width of the address of the bank is 15 bits(14~0),so
//the sram_addr[15] is the minimun of the next bank. If its
//value is "1",it means the next bank is selcted.
//在 “五、总结”中介绍了不同bit的数据传输的片,块选择
assign sram_csn_en = (sram_write || sram_read);
assign bank_sel = (sram_csn_en && (sram_addr[15] == 1'b0)) ? 1'b1 : 1'b0;
assign bank0_csn = (sram_csn_en && (sram_addr[15] == 1'b0))? sram_csn : 4'b1111;
assign bank1_csn = (sram_csn_en && (sram_addr[15] == 1'b1))? sram_csn : 4'b1111;
//signals used to generation sram chip select signal in one bank.
assign haddr_sel = sram_addr[1:0];
assign hsize_sel = hsize_r[1:0];
//----------------------------------------------------------
//data from ahb writing into sram
//----------------------------------------------------------
assign sram_wdata = hwdata;
//----------------------------------------------------------
//Generate the sram chip selecting signals in one bank,
//The resluts show the AHB bus write or read how many data
//once a time: byte,halfword or word
//----------------------------------------------------------
always @(hsize_sel or haddr_sel)
begin
if(hsize_sel == 2'b10)
sram_csn = 4'b0;
// 01为传输16bit数据,将两块sram绑定,通过haddr_sel[1]来判断选择低两块还是高两块,低电平有效
else if(hsize_sel == 2'b01)
begin
if(haddr_sel[1] == 1'b0)
sram_csn = 4'b1100;
else
sram_csn = 4'b0011;
end
// 00传输8bit数据,再根据haddr_sel来判断选择bank中的哪个cs,低电平有效
else if(hsize_sel == 2'b00)
begin
case(haddr_sel)
2'b00 : sram_csn = 4'b1110;
2'b01 : sram_csn = 4'b1101;
2'b10 : sram_csn = 4'b1011;
2'b11 : sram_csn = 4'b0111;
default : sram_csn = 4'b1111;
endcase
end
else
sram_csn = 4'b1111;
end
//-------------------------------------------------
//sequential portion
//-------------------------------------------------
//tmp the ahb address and control signals
always @(posedge hclk or negedge hresetn)
begin
if(!hresetn)
begin
hwrite_r <= 1'b0;
hsize_r <= 3'b0;
hburst_r <= 3'b0;
htrans_r <= 2'b0;
haddr_r <= 32'b0;
end
//将控制信号和地址信号打拍,对应数据。因为数据晚一个cyle传入
else if(hsel && hready)
begin
hwrite_r <= hwrite;
hsize_r <= hsize;
hburst_r <= hburst;
htrans_r <= htrans;
haddr_r <= haddr;
end
else
begin
hwrite_r <= 1'b0;
hsize_r <= 3'b0;
hburst_r <= 3'b0;
htrans_r <= 2'b0;
haddr_r <= 32'b0;
end
end
endmodule
五、总结
-
支持8/16/32位的SRAM数据读写操作
通过hsize[1:0]来选择位数
00:8bit,深度为2^16,haddr的有效范围[15:0];
haddr[15]选择bank:haddr[15] == 0:bank0;haddr[15] == 1:bank1;
01:16bit,深度为2^15,haddr的有效范围[14];
将两片cs绑定
haddr[13]为cs片选:
bank0:
haddr[13] == 0:cs0,cs1
haddr[13] == 0:cs2,cs3
bank1:
haddr[13] == 0:cs4,cs5
haddr[13] == 0:cs6,cs7
10:32bit,深度为2^14,haddr有效范围[13:0]
haddr[13]为块选:
haddr[13] == 0:bank0
haddr[13] == 1:bank1 -
支持低功耗工作
将64k分成8块8k,由4片组成一个bank-bank0,bank1。根据不同的地址,选择一块或者多块SRAM,未被选中的SRAM处于low-power standby状态。 -
支持单周期读写
一个周期读,一个周期写
AHB总线数据传输具有地址周期和数据周期,AHB的地址信号和控制信号发送完毕后,下一个周期才发送数据,而SRAM的写时序是同时输入地址和数据的,所以要对ahb的地址和控制信号进行打拍处理。