AHB-SRAMC Design-01
AHB-SRAMC Design
1.AHB-SoC芯片架构图
- CPU赋予了SoC的可编程性
- SRAM可以存储数据和代码
2.AHB-SRAMC Features
- 总线版本号
- 在进行设计的时候可以将地址位宽进行参数化设计
3. AHB-SMRC Specication
4. AHB-SRAMC Architecture
5. AHB Operation Timing:Basic Transfer
6. AHB Transfer Types
- BUSY是在burst传输期间,还没有准备好下一笔请求使用BUSY;IDLE是被授予了权限但是还没有发起burst传输
7.AHB Burst Transaction
8.AHB Transaction Reponse
9.AHB Slave Interface
- split是可选的
10.SRAM Specification
11.SRAM Timing
12.SRAM logic table
- CEN 拉高,OEN拉低 -- standby模式,输出上一笔输出,这种模式下功耗较低
13.SRAM power
14.SRAMC Architecture
15.hclk vs sram_clk
16.RTL Coding
16.1 ahb_slave_if module
//由微架构设计文档转换为RTL代码
//AHB_Slave_Interface
module ahb_slave_if(
// input
input hclk,
input hresetn,
// Signals from AHB bus used during nomal operation
input sel,
input hwrite,
input hready,
input [2:0] hsize,
input [2:0] hburst,
input [1:0] htrans,
input [31:0] hwdata,
input [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,
// output
// Signals to AHB bus used during nomal 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
output [3:0] bank0_csn, // 写片选
output [3:0] bank1_csn,
//Signals to sram core in nomal operation,it contains sram
//address and data writing into sram
output [12:0] sram_addr_out, // 地址
output [31:0] sram_wdata, // 数据
);
// htrans的状态
parameter IDLE = 2'b00,
BUSY = 2'b01,
NONSEQ = 2'b10,
SEQ = 2'b11;
// hsize
parameter HALF_WORD = 2'b00,
WORD = 2'b01,
BYTE = 2'b10,
// 控制信号delay,将ahb的address信号打一拍
reg hwrite_r;
reg [2:0] hsize_r;
reg [2:0] hburst_r;
reg [1:0] htrans_r;
reg [31:0] haddr_r;
// 定义标志打拍的信号
wire delay_en;
// 有效的data phase的时候将ahb信号delay
assign delay_en = hsel && (htrans == NONSEQ || htrans == SEQ) && hready;
// 1. 将地址和控制信号进行打一拍
// hrestn为低的时候进行复位
// 当hsel && hready && htrans ==
always @(posedge hclk or negedge hresetn) begin
if(!hresetn) begin
hwrite_r <= 'b0;
hsize_r <= 'b0;
hburst_r <= 'b0;
htrans_r <= 'b0;
haddr_r <= 'b0;
end
else if(delay_en) begin
hwrite_r <= hwrite;
hsize_r <= hsize;
hburst_r <= hburst;
htrans_r <= htrans;
haddr_r <= haddr;
end
end
// 2.产生控制信号,根据输出信号进行产生
assign hready_resp = 1'b1; // 永远有效
assign hresp = 2'b0; // ok状态
// sram_w_en 是1bit信号,广播到8个mem中的,所以直接用hwrite取反就可以
// 因为低电平有效所以直接取反
assign sram_w_en = !hwrite_r;
// 先不管bank0和bank1,就假设已经选择了一个bank,哪些bank中的mem被选中
// sram_csn -- sram片选,不管哪个bank被选中,看其中到底选中哪个mem
// 根据hsize和haddr[1:0]进行确定的
reg [3:0] sram_csn;
always @(*) begin
if(hsize_r == BYTE) begin
case(haddr[1:0])
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'b0111;
endcase
end
else if(hsize == HALF_WORD) begin
sram_csn = haddr_r[1] ? 4'b0011 : 4'b1100;
end
else if(hsize == WORD) begin
sram_csn = 4'b0000;
end
else begin
sram_csn = 4'b1111;
end
end
// delay_en信号为高的时候,当前有一个有效的请求,一定是对当前sram进行读写操作
// 所以通过delay信号可以产生bank选择信号
// delay_en信号拉高之后的下一个周期就会发起请求,所以将delay信号打一拍
reg delay_en_r;
always @(posedge hclk or negedge hresetn) begin
if(!hresetn) begin
delay_en_r <= 'b0;
else
delay_en_r <= delay_en;
end
// delay_en_r为高并且最高位为0,选择bank0,最高位为1,选择bank1
// 当前是读写操作并且最高位为0,选择bank0
assign bank0_csn = (delay_en_r && !haddr[15]) ? sram_csn :4'b1111;
// 当前是读写操作并且最高位为0,选择bank1
assign bank1_csn = (delay_en_r && haddr[15]) ? sram_csn : 4'b1111;
// haddr_r为32bit,其中有16bit有用,取其中16bit中的中间13bit表示地址
assign sram_addr_out = haddr_r[14:2];
assign sram_wdata = hwdata;
// 读数据根据当前选择的bank0还是bank1,将其中的四个sram输出的数据进行拼接得到32bit的hrdata
assign hrdata = haddr[15] ? {sram_q7,sram_q6,sram_q5,sram_q4};
assign hrdata = haddr[15] ? {sram_q3,sram_q2,sram_q1,sram_q0};
endmodule
module ahb_sram_if (
input clk,
input hrestn,
input [31:0] hwdata,
inpu hsel,
input [2:0] hsize,
input [1:0] htrans,
input [2:0] hburst,
input [15:0] haddr,
input hwrite,
input hready,
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,
output hready_resp,
output [1:0] hresp,
output [31:0] hrdata,
// 产生读写使能
output sram_w_en,
// 输出读地址,根据bank
output sram_addr_out,
// 产生bank的片选
output [3:0] bank0_csn,
output [3:0] bank1_csn,
output wdata
);
// 定义htrans的状态
parameter IDLE = 2'b00,
BUSY = 2'b01,
NONSEQ = 2'b10,
SEQ = 2'b11;
// 定义hsize的大小
parameter HALF_WORD = 2'b00,
WORD = 2'b01,
BYTE = 2'b10,
// 控制信号delay
reg hwrite_r;
reg [2:0] hsize_r;
reg [2:0] hburst_r;
reg [1:0] htrans_r;
reg [31:0] haddr_r;
// 处理ahb时序,将ahb时序打拍
// 定义一个标志什么时候延迟打拍的信号delay_en
// 这是一个模块内部的连线
wire delay_en;
assign delay_en = hsel && hready && (htrans == NONSQE || htrans == SQE);
always @(posedge hclk or negedge hrestn) begin
if(!hrestn) begin
hwrite_r <= 'b0;
hsize_r <= 'b0;
hburst_r <= 'b0;
htrans_r <= 'b0;
haddr_r <= 'b0;
end
else if(delay_en) begin
hwrite_r <= hwrite;
hsize_r <= hsize;
hburst_r <= hburst;
htrans_r <= htrans;
haddr_r <= haddr;
end
end
// 单周期读写,hreay_out没有延迟,所以将hready_resp固定为高
// 将hresp选择okay
assign hready_resp = 1'b1; // 永远有效
assign hresp = 2'b0; // ok状态
// 上面处理完ahb时序之后,将产生sram控制信号
// 1.产生读写使能 -- 将ahb的读写信号反相
assign sram_w_en = !hwrite_r;
// 2.产生片选信号
// 首先定义一个sram_csn信号表示选择哪几个mem(不管选择哪个bank)
// 选择哪个mem是由hsize和地址的低两位进行确定的
reg [3:0] sram_csn;
always @(*) begin
if(hsize_r == BYTE) begin
case(haddr[1:0])
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'b0111;
endcase
end
else if(hsize == HALF_WORD) begin
sram_csn = haddr_r[1] ? 4'b0011 : 4'b1100;
end
else if(hsize == WORD) begin
sram_csn = 4'b0000;
end
else begin
sram_csn = 4'b1111;
end
end
// 上面处理完选择mem的信号之后,产生选择bank的信号
// 选择bank要根据地址,所以时序与delay信号一致
// 因为delay信号的下一个周期一定会发起读写请求,所以将delay_en打一拍
// 产生bank的选择信号
// delay信号为高的时候,一定是对当前sram进行读写操作
// 所以通过delay信号可以产生bank选择信号
// delay信号拉高之后的下一个周期就会发起请求,所以将delay信号打一拍
reg delay_en_r;
always @(posedge hclk or negedge hresetn) begin
if(!hresetn) begin
delay_en_r <= 'b0;
else
delay_en_r <= delay_en;
end
// delay_en_r为高并且最高位为0,选择bank0,最高位为1,选择bank1
assign bank0_csn = (delay_en_r && !haddr[15]) ? sram_csn : 4'b1111;
assign bank1_csn = (delay_en_r && haddr[15]) ? sram_csn : 4'b1111;
// 输出结果信号
// 由ahb的地址中间的十三位得到sram中mem的地址
assign sram_addr_out = haddr_r[14:2];
// 由ahb总线上的数据得到写入sram中的数据
assign sram_wdata = hwdata;
// 输出的读数据根据选择的bank进行输出,地址最高位就是bank选择的信号
assign hrdata = haddr[15] ? {sram_q7,sram_q6,sram_q5,sram_q4};
assign hrdata = haddr[15] ? {sram_q3,sram_q2,sram_q1,sram_q0};
endmodule
16.2 sramc_top
- 顶层不写交互逻辑
module sramc_top (
// input signals
hclk,
sram_clk,
hresetn,
hsel,
hwrite,
hready,
hsize,
htrans,
hburst,
hwdata,
haddr,
dft_en,
bist_en,
// output signals
hready_resp,
hresp,
hrdata,
bist_done,
bist_fail
);
// list of AHB signals
// signals used during normal operation
input hclk;
input sram_clk;
input hresetn;
// Signals from AMBA bus used during normal operation
input sel;
input hwrite;
input hready;
input [2:0] hsize;
input [2:0] hburst;
input [1:0] htrans;
input [31:0] hwdata;
input [31:0] haddr;
// Signals to AMBA bus used during normal operation
output hready_resp;
output [1:0] hresp;
output [31:0] hrdata;
// Signals for BIST and DFT test mode
// When signal "dft_en" or "bist_en" is high,sram
// controller enters into test mode.
input dft_en;
input bist_en;
//When "bist_done" is high,it shows BIST test is over
output bist_done;
//"bist_fail" shows the results of each sram functions.
//There are 8 srams in the controller.
output [7:0] bist_fail;
//Select one of the two sram blocks according to the value of sram_csn
wire [3:0] bank0_csn;
wire [3:0] bank1_csn;
//Sram read or write signals:When it is high ,read sram ;low write sram
wire sram_w_en;
//Each of 8 srams is 8k*8,the depth is 2^13,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.value
ahb_slave_if U_ahb_slave_if (
// AHB input signals into sram controller
.hclk (hclk),
.hresetn (hresetn),
.sel (hsel),
.write (hwrite),
.hready (hready),
.hsize (hsize),
.htrans (htrans),
.hburst (hburst),
.hwdata (hwdata),
.haddr (haddr),
//8 sram blocks 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),
.sram_q8 (sram_q8),
//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 correponding sram in a bank,active low
.bank0_csn (bank0_csn),
.bank1_csn (bank1_csn)
);
sram_core U_sram_core(
// AHB bus signals
.hclk (hclk),
.sram_clk (sram_clk)
.hresetn (hresetn),
//sram control signals from ahb_slave_if.v
.sram_addr (sram_addr),
.sram_wdata_in (sram_wdata),
.sram_wen (sram_w_en),
.bank0_csn (bank0_csn),
.bank1_csn (bank1_csn),
//test mode enable signals
.bist_en (bist_en),
.dft_en (dft_en),
//8 sram 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),
.sram_q8 (sram_q8),
//test results output when in test mode
.bist_done (bist_done),
.bist_fail (bist_fail)
);
endmodule