SRAM在整个系统中作为缓存,SRAM控制器实现SRAM存储器与AHB总线的数据信息交换,其一端连接AHB总线,另一端连接SRAM(8k*8两个bank),将AHB总线上的读写操作转换成标准的SRAM读写操作(将控制信号和地址信号及数据信号进行转化,并将其发送给相应的SRAM存储器,进行实际的数据存取)。
AHB-SRAMC设计规格:
主要注意2个问题:
sramc_top是顶层模块作为SRAM的控制器,包括ahb_sram_if和sram_core 两个模块。其中ahb_sram_if 连接sram控制器到AHB总线并且生成SRAM的控制信号(SRAM的地址,读写信号,片选信号等);sram_core包含了8个sram并作为sram的顶层,并包含了DFT和BIST部分。
Top: sramc_top:作为顶层模块,连接ahb_sram_if和sram_core模块。
信号描述:
Signal | I/O | width | source | Descriptions | |
---|---|---|---|---|---|
hclk | input | 1 | Clock source | Bus clock | |
sram_clk | input | 1 | Clock source | sram clock | |
hrestn | input | 1 | Reset controller | Reset | |
hsel | input | 1 | Decoder | Slave select | AHB control |
htranst | input | [1:0] | Master | Transfer type:NONSEQ, SEQ,IDLE,BUSY | |
hwrite | input | 1 | Master | Transfer direction | |
hsize | input | [2:0] | Master | Transfer size | |
hburst | input | [2:0] | Master | Burst type | |
haddr | input | [31:0] | Master | Address bus | |
hwdata | input | [31:0] | Master | Write data bus | |
hready | output | 1 | Slave | Transfer done | |
hresp | output | 1 | Slave | Transfer response(status) | |
hrdata | output | [31:0] | Slave | Read data bus |
ahb_slave_if模块是连接AHB总线和sram的接口模块,将AHB总线的控制信号、地址信号以及数据信号进行转化,并将其发送给相应的SRAM存储器。
Signal | I/O | Width | Source | Descriptions |
---|---|---|---|---|
hclk | input | 1 | Clock source | Bus clock |
hrestn | input | 1 | Reset controller | Reset |
hsel | input | 1 | Decoder | Slave |
htranst | input | [1:0] | Master | Transfer type:NONSEQ, SEQ, IDLE,BUSY |
hwrite | input | 1 | Master | Transfer direction:1-write 0-read |
hsize | input | [2:0] | Master | Transfer size: byte (8-bit), halfword (16-bit) or word (32-bit). max :1024bit |
hburst | input | [2:0] | Master | Burst type:SIGNAL,INCR1/4/8/16,WAPR4/8/16 |
haddr | inpu | [31:0] | Master | Address bus |
hwdata | input | [31:0] | Master | Write data bus |
sram_q0-q7 | input | [7:0] | sram | sram output data |
hready | output | 1 | Slave | Transfer done |
hresp | output | [1:0] | Slave | Transfer response(status): OKAY ,ERROR,RETRY ,SPLIT |
hrdata | output | [31:0] | Slave | Read data bus |
sram_w_en | output | 1 | sram | write enable :write:0;read:1 |
sram_addr_out | output | [12:0] | sram address | |
sram_wdata | output | [31:0] | sram write data | |
bank0_csn | output | [3:0] | sram bank0 select | |
bank1_csn | output | [3:0] | sram bank1 select |
module ahb_slave_if(
//input signals
input hclk,
input hresetn,
input hsel,
input hwrite,
input hready,
input [2:0] hsize,
input [1:0] htrans,
input [2:0] hburst, // hard code -> parameter
input [31:0] hwdata,
input [31:0] haddr,
//output signals
output hready_resp,
output [1:0] hresp,
output [31:0] hrdata,
//sram output
input [7:0] sram_q0, // 8bits
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,
//sram control signal
output sram_w_en, // 0:write, 1:read
output [12:0] sram_addr_out,
output [31:0] sram_wdata, //写sram数据
output [3:0] bank0_csn, //四字节可以单独写入
output [3:0] bank1_csn
);
//-------------------------------------------------------
//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 address from AHB bus
wire [31:0] sram_data_out; //data read from sram and send to AHB bus
parameter IDLE = 2'b00,
BUSY = 2'b01,
NONSEQ = 2'b10,
SEQ = 2'b11;
//---------------------------------------------------------
// 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; // Singal Cycle
assign hresp = 2'b00; // OK
//---------------------------------------------------------
//sram data output to AHB bus
//---------------------------------------------------------
assign hrdata = sram_data_out; //组合逻辑读,CPU读SRAM,地址有效则立即读
//Choose the right data output of the two banks(bank0, bank1) according
//to the value of bank_sel. If bank_sel = 1'b1, bank0 sleceted, or
//bank1 selected.
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.
assign sram_write = ((htrans_r == NONSEQ) || (htrans_r == SEQ)) && hwrite_r;
assign sram_read = ((htrans_r == NONSEQ) || (htrans_r == SEQ)) && (!hwrite_r);
assign sram_w_en = !sram_write;
//generate sram address
//SRAM总寻址64K 0x0--0xffff
assign sram_addr = haddr_r [15:0];//64K 8*8K
assign sram_addr_out = sram_addr[14:2]; // word
//Generate bank select signals by the value of sram_addr[15].
//Each bank(32kx32) comprises of four sram block(8kx8), 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.
assign sram_csn_en = (sram_write || sram_read);
//低32K bank0 高32K bank1
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 generating 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)//32bit
sram_csn = 4'b0;
else if(hsize_sel == 2'
) begin//16bit
if(haddr_sel[1] == 1'b0) //little-endian
sram_csn = 4'b1100;
else
sram_csn = 4'b0011;
end
else if(hsize_sel == 2'b00) begin//8bit
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 , 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
else if(hsel && hready) begin //hsel要片选,否则信号一直在翻转,可能会功能错误,并且功耗大
hwrite_r <= hwrite ;//写SRAM时,把控制信号寄存。因为写操作时,要把地址打一拍,和数据对齐
hsize_r <= hsize ;
// hburst_r <= hburst ;//AHB中master会把burst传输所有地址传递过来,AXI只传递起始地址。此处用处不大。减少一个REG
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
sram_core:两个bank,每个bank 4个SRAM(8Kx8)
sram逻辑真值表:
signal | I/O | width | description | |
---|---|---|---|---|
hclk | input | 1 | AHB bus clock | AHB bus signals |
sram_clk | input | 1 | sram clock | AHB bus signals |
hresern | input | 1 | reset | AHB bus signals |
sram_addr | input | [12:0] | sram address | sram control signals form ahb_sram_if |
sram_wdata | input | [31:0] | sram write data | sram control signals form ahb_sram_if |
sram_wen | input | 1 | sram write enable :write:0;read:1 | sram control signals form ahb_sram_if |
bank0_csn | input | [3:0] | sram bank0 select | sram control signals form ahb_sram_if |
bank1_csn | input | [3:0] | sram bank1 select | sram control signals form ahb_sram_if |
bist_en | input | 1 | bist enable | test model enable |
dft_en | input | 1 | dft enable | test model enable |
sram_q0-q7 | output | [7:0] | sram data 8bit | 8 sram data output into AHB bus |
bist_done | output | 1 | bist done | test model ouput flag |
module sram_core(
hclk,
sram_clk,
hreset_n,
sram_addr,
sram_wdata,
sram_wen,
bank0_csn,
bank1_csn,
dft_en,
bist_en,
sram_q0,
sram_q1,
sram_q2,
sram_q3,
sram_q4,
sram_q5,
sram_q6,
sram_q7,
bist_done,
bist_fail,
);
input hclk;
input sram_clk;
input hreset_n;
input [12:0] sram_addr;
input [31:0] sram_wdata;
input sram_wen; //low :write ; high :read
input [3:0] bank0_csn;
input [3:0] bank1_csn;
input dft_en;
input bist_en;
output wire [7:0] sram_q0;
output wire [7:0] sram_q1;
output wire [7:0] sram_q2;
output wire [7:0] sram_q3;
output wire [7:0] sram_q4;
output wire [7:0] sram_q5;
output wire [7:0] sram_q6;
output wire [7:0] sram_q7;
output bist_done;
output [7:0] bist_fail;
//Every sram bist's work state and results output.
wire bist_done0;
wire bist_fail0;
wire bist_done1;
wire bist_fail1;
wire bist_done2;
wire bist_fail2;
wire bist_done3;
wire bist_fail3;
wire bist_done4;
wire bist_fail4;
wire bist_done5;
wire bist_fail5;
wire bist_done6;
wire bist_fail6;
wire bist_done7;
wire bist_fail7;
wire bank0_bistdone;
wire bank1_bistdone;
wire [3:0] bank0_bistfail;
wire [3:0] bank1_bistfail;
//bist finishing state of bank0
assign bank0_bistdone = (bist_done3 && bist_done2) && (bist_done1 && bist_done0);
//bist results of bank0
assign bank0_bistfail = {bist_fail3,bist_fail2,bist_fail1,bist_fail0};
//bist finishing state of bank1
assign bank1_bistdone = (bist_done7 && bist_done6) && (bist_done5 && bist_done4);
//bist results of bank1
assign bank1_bistfail = {bist_fail7,bist_fail6,bist_fail5,bist_fail4};
//--------------------------------------------------------------------------
//the 8 srams results of BIST test and the finishing state
//--------------------------------------------------------------------------
assign bist_done = bank0_bistdone && bank1_bistdone;
assign bist_fail = {bank1_bistfail,bank0_bistfail} ;
//-------------------------------------------------------------------------
//Instance 8 srams and each provides with BIST and DFT functions.
//Bank0 comprises of sram0~sram3, and bank1 comprises of sram4~sram7.
//In each bank, the sram control signals broadcast to each sram, and data
//written per byte into each sram in little-endian style.
//-------------------------------------------------------------------------
//bank0 bank1读写使能以及地址都完全相同,写入的数据也相同
ram_bist u_sram_bist0(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank0_csn[0]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[7:0]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q0),
.bist_done (bist_done0),
.bist_fail (bist_fail0)
);
ram_bist u_sram_bist1(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank0_csn[1]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[15:8]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q1),
.bist_done (bist_done1),
.bist_fail (bist_fail1)
);
ram_bist u_sram_bist2(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank0_csn[2]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[23:16]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q2),
.bist_done (bist_done2),
.bist_fail (bist_fail2)
);
ram_bist u_sram_bist3(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank0_csn[3]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[31:24]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q3),
.bist_done (bist_done3),
.bist_fail (bist_fail3)
);
ram_bist u_sram_bist4(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank1_csn[0]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[7:0]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q4),
.bist_done (bist_done4),
.bist_fail (bist_fail4)
);
ram_bist u_sram_bist5(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank1_csn[1]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[15:8]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q5),
.bist_done (bist_done5),
.bist_fail (bist_fail5)
);
ram_bist u_sram_bist6(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank1_csn[2]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[23:16]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q6),
.bist_done (bist_done6),
.bist_fail (bist_fail6)
);
ram_bist u_sram_bist7(
.hclk (hclk),
.sram_clk (sram_clk),
.sram_rst_n (hreset_n),
.sram_csn_in (bank1_csn[3]),
.sram_wen_in (sram_wen),
.sram_addr_in (sram_addr),
.sram_wdata_in (sram_wdata[31:23]),
.bist_en (bist_en),
.dft_en (dft_en),
.sram_data_out (sram_q7),
.bist_done (bist_done7),
.bist_fail (bist_fail7)
);
endmodule