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
posted @ 2023-03-12 12:20  Icer_Newer  阅读(175)  评论(0编辑  收藏  举报