基于AHB总线的sram控制器设计

目录

  • AHB-SRAMC介绍
  • 具体模块设计
    • ahb_slave_if
      • 信号描述
      • Verilog实现
    • sram_core
      • 信号描述
      • verilog实现

AHB-SRAMC介绍

SRAM在整个系统中作为缓存,SRAM控制器实现SRAM存储器与AHB总线的数据信息交换,其一端连接AHB总线,另一端连接SRAM(8k*8两个bank),将AHB总线上的读写操作转换成标准的SRAM读写操作(将控制信号和地址信号及数据信号进行转化,并将其发送给相应的SRAM存储器,进行实际的数据存取)。
基于AHB总线的sram控制器设计_第1张图片
AHB-SRAMC设计规格

  • 支持8位、16位和32位的SRAM数据读写操作;
  • 支持SRAM单周期读写(直接影响Soc性能);
  • 支持在多块SRAM组成的存储器中,根据不同地址系统选择一块或者多块SRAM。未被选中的SRAM则处于 low power standby状态。(低功耗)

主要注意2个问题:

  • AHB总线传输,数据位宽有 8/16/32的传输模式,而sram不一定支持。这里采用4个sram来实现,每块sram对应一个byte。
  • AHB总线时序和sram时序的转化。AHB总线数据传输具有地址周期和数据周期,AHB的地址和控制信号发送完毕后,下一个周期才发送数据,而sram的写时序是同时输入地址和数据,所以这里对AHB的地址和控制信号做打拍处理。

具体模块设计

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模块。
基于AHB总线的sram控制器设计_第2张图片

信号描述:

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_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

Verilog实现

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

sram_core:两个bank,每个bank 4个SRAM(8Kx8)
基于AHB总线的sram控制器设计_第3张图片
sram逻辑真值表:
基于AHB总线的sram控制器设计_第4张图片

信号描述

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

verilog实现

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 

你可能感兴趣的:(数字IC设计,AHB)