AHB-SRAM简单设计之内部模块 sram_core.v

前言

他们都说这一部分不需要自己设计,还说了公司里面这部分都是买的,dft和bist前期就不用介入工作,因为买的IP里面已经集成进去了。如果公司没买IP,都是自己做的,那就需要前期和设计工程师一起交流,留下接口。

仅从设计层面来讲,sram_core.v的复杂程度也挺高的(仅针对小编小白)!所以,这部分打算直接附带码,先不做任何解释!如果后面还想分析,再附!
在这里插入图片描述

内部模块 sram_core.v

结合上面的图和下面的代码,理解:sram_core就是在里面例化了8片sram_bist

module sram_core(
  //input signals
  input			    hclk,
  input			    sram_clk,
  input			    hresetn,
  
  input			    sram_wen,        // =1 读sram; =0,写sram.8个一起读或者一起写
  input	[12:0]	sram_addr,
  input	[31:0]	sram_wdata_in,   //data write into sram when "sram_wen_in" active low
  input	[3:0]	  bank0_csn,       //两个bank,每个bank有四个片选
  input	[3:0]	  bank1_csn,
  input			    bist_en,         //BIST test mode
  input	    	  dft_en,          //DFT test mode
          
  //output signals
  output [7:0]	sram_q0,
  output [7:0]	sram_q1,
  output [7:0]	sram_q2,
  output [7:0]	sram_q3,
  output [7:0]	sram_q4,
  output [7:0]	sram_q5,
  output [7:0]	sram_q6,
  output [7:0]	sram_q7,
                    
  output			  bist_done,  //When "bist_done" is high, it shows BIST test is over.
  output [7:0]  bist_fail   //"bist_fail" shows the results of each sram funtions.
  );
 
  //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读写使能以及地址都完全相同,写入的数据也相同

  sram_bist u_sram_bist0(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank0_csn[0]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[7:0]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q0),
                        .bist_done        (bist_done0),
                        .bist_fail        (bist_fail0)  
                       );

  sram_bist u_sram_bist1(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank0_csn[1]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[15:8]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q1),
                        .bist_done        (bist_done1),
                        .bist_fail        (bist_fail1)  
                       );

  sram_bist u_sram_bist2(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank0_csn[2]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[23:16]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q2),
                        .bist_done        (bist_done2),
                        .bist_fail        (bist_fail2)  
                       );

  sram_bist u_sram_bist3(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank0_csn[3]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[31:24]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q3),
                        .bist_done        (bist_done3),
                        .bist_fail        (bist_fail3)  
                       );

  sram_bist u_sram_bist4(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank1_csn[0]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[7:0]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q4),
                        .bist_done        (bist_done4),
                        .bist_fail        (bist_fail4)  
                       );

  sram_bist u_sram_bist5(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank1_csn[1]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[15:8]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q5),
                        .bist_done        (bist_done5),
                        .bist_fail        (bist_fail5)  
                       );

  sram_bist u_sram_bist6(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank1_csn[2]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[23:16]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                   
                        .sram_data_out    (sram_q6),
                        .bist_done        (bist_done6),
                        .bist_fail        (bist_fail6)  
                       );
		  
  sram_bist u_sram_bist7(
                        .hclk             (hclk),
                        .sram_clk         (sram_clk),
                        .sram_rst_n       (hresetn),
                        .sram_csn_in      (bank1_csn[3]),
                        .sram_wen_in      (sram_wen),
                        .sram_addr_in     (sram_addr),
                        .sram_wdata_in    (sram_wdata_in[31:24]),
                        .bist_en          (bist_en),
		                .dft_en           (dft_en),
                                     
                        .sram_data_out    (sram_q7),
                        .bist_done        (bist_done7),
                        .bist_fail        (bist_fail7)  
                       );

endmodule

单纯设计这个内部模块,现在真的拿不下!这个sram_core.v下面又例化了sram_bist.v,下面继续上sram_bist.v的文件。

sram_bist.v

到这一部分,突然想起来,有人一直在群里问,你们有memory_bist吗?有人回答,在某个软件下面有自带的ip,用就行。所以这部分,也是套用即可(当然,以后套用肯定要懂得原理呀)!

module sram_bist(
  //input signals
  input         hclk,
  input         sram_clk,
  input         sram_rst_n,
  input         sram_csn_in,   //chip select enable 
  input         sram_wen_in,   //sram write or read enable; 0:write; 1:read
  input[12:0]   sram_addr_in, 
  input[7:0 ]   sram_wdata_in,
  input         bist_en,       // MBIST mode
	input         dft_en,        // DFT mode
  
  //output signals
  output[7:0 ]  sram_data_out, 
  output        bist_done,     // 1: test over
  output        bist_fail      // high: MBIST Fail
  );
				
  //----------------------------------------------------
  //Internal signals connected the sram with bist module 
  //when "bist_en" active high.
  //----------------------------------------------------
  wire sram_csn;
  wire sram_wen;
  wire sram_oen;
  wire [12:0] sram_a;
  wire [7:0]  sram_d;
  wire [7:0]  data_out;

  //Sram output data when "dft_en" active high.
  wire [7:0] dft_data;
  reg [7:0]  dft_data_r;
 
  wire [12:0] sram_addr;
  wire [7:0]  sram_wdata;

  //clock for bist logic, when bist is not work, clock should be 0.
  wire bist_clk;

  genvar K;
  
  //block sram input when cs is diable for low power design 
  assign sram_addr = sram_csn_in ? 0 : sram_addr_in;
  assign sram_wdata = sram_csn_in ? 0 : sram_wdata_in;

  //dft test result
  assign dft_data = (sram_d ^ sram_a[7:0]) ^ {sram_csn, sram_wen, sram_oen, sram_a[12:8]}; 

  always @(posedge hclk or negedge sram_rst_n) begin
    if(!sram_rst_n)
      dft_data_r <= 0;
    else if(dft_en)
      dft_data_r <= dft_data;
  end

  //sram data output
  assign sram_data_out = dft_en ? dft_data_r : data_out;
  // Note: Need to take place the mux using the special library cell
/*
  generate for(K = 0; K < 8; K = K+1 )
    begin :hold
    //BHDBWP7T holdQ (.Z(data_out[K]));
    end 
  endgenerate
*/

  //clock for bist logic, when bist is not work, clock should be 0.
  // Note: Need to take place the mux using the special library cell
  // CKMUX2D2BWP7T U_bist_clk_mux (.I0(1'b0), .I1(hclk), .S(bist_en), .Z(bist_clk));
  assign bist_clk = bist_en ? hclk : 1'b0;

  // One sram with BIST and DFT function
  RA1SH u_RA1SH(
        .Q      (data_out),
        .CLK    (sram_clk),
        .CEN    (sram_csn),
        .WEN    (sram_wen),
        .A      (sram_a),
        .D      (sram_d),
        .OEN    (sram_oen)
       );

  mbist_8kx8 u_mbist_8kx8(
        .b_clk   (bist_clk),
        .b_rst_n (sram_rst_n),
        .b_te    (bist_en),
		     //--------------------------------------------------------
		     //All the input signals will be derectly connected to
		     //the sram input when in normal operation; and when in
		     //BIST TEST mode, there are some mux in BIST module
		     //selcting all sram input signals which generated by itself:
		     //sram controll signals, sram write data, etc.
		     //--------------------------------------------------------
         .addr_fun     (sram_addr),
         .wen_fun      (sram_wen_in),
         .cen_fun      (sram_csn_in),
         .oen_fun      (1'b0),
         .data_fun     (sram_wdata),

         .ram_read_out (sram_data_out),
         .data_test    (sram_d),
         .addr_test    (sram_a),
         .wen_test     (sram_wen),
         .cen_test     (sram_csn),
         .oen_test     (sram_oen),

         .b_done       (bist_done),
         .b_fail       (bist_fail)
       );

endmodule

这个sram_bist下面又例化了 RA1SH和mbist_8kx8两个模块,这是最后一层例化了。下面附这两个模块的代码!

mbist_8kx8.v

这个模块,里面的状态机啥的,都值得借鉴,如果有时间,建议抠熟!

module mbist_8kx8 
#(parameter WE_WIDTH = 1,
  parameter ADDR_WIDTH = 13,
  parameter DATA_WIDTH = 8
 )
 (
  //input signals
  input                      b_clk,    // bist clock	
  input                      b_rst_n,  // bist resetn
  input                      b_te,     // bist enable
  input [(ADDR_WIDTH-1):0]   addr_fun,
  input [(WE_WIDTH-1):0]     wen_fun,
	input                      cen_fun,
	input                      oen_fun,
	input [(DATA_WIDTH-1):0]   data_fun,
	input [(DATA_WIDTH-1):0]   ram_read_out,
  //output signals
	output [(ADDR_WIDTH-1):0]  addr_test, // address of test
	output [(WE_WIDTH-1):0]    wen_test,  // writing control of bist test mode
	output                     cen_test,  // chip enable control of bist test mode
	output                     oen_test,  // output enable control of bist test mode
  output [(DATA_WIDTH-1):0]  data_test, // data input of bist test mode
	output				             b_done,    // output state of bist test mode
                                        // When "bist_done" is high, it shows BIST test is over.

	output reg                 b_fail     // output result of sram function
                                        // When "bist_fail" is high, the sram function is wrong;
                                        // else, the sram function is right.
  );

  //----------------------------------------------------
  //Define 27 work states of BIST block for bist test
  //----------------------------------------------------
  `define IDEL1         5'b00000
  `define P1_WRITE0     5'b00001
  `define IDEL2         5'b00010
  `define P2_READ0      5'b00011
  `define P2_COMPARE0   5'b00100
  `define P2_WRITE1     5'b00101
  `define IDEL3         5'b00110
  `define P3_READ1      5'b00111
  `define P3_COMPARE1   5'b01000
  `define P3_WRITE0     5'b01001
  `define P3_READ0      5'b01010
  `define P3_COMPARE0   5'b01011
  `define P3_WRITE1     5'b01100
  `define IDEL4         5'b01101
  `define P4_READ1      5'b01110
  `define P4_COMPARE1   5'b01111
  `define P4_WRITE0     5'b10000
  `define IDEL5         5'b10001
  `define P5_READ0      5'b10010
  `define P5_COMPARE0   5'b10011
  `define P5_WRITE1     5'b10100
  `define P5_READ1      5'b10101
  `define P5_COMPARE1   5'b10110
  `define P5_WRITE0     5'b10111
  `define IDEL6         5'b11000
  `define P6_READ0      5'b11001
  `define P6_COMPARE0   5'b11010
  
  // sram address when in bist test mode
  reg [(ADDR_WIDTH-1):0] test_addr;
  
  // bist test end signal
  reg r_end;
  reg r_end_en;
 
  // sram address reset when in bist test mode.
  reg test_addr_rst;

  // sram read or write enable signal when in bist test mode
  reg [(WE_WIDTH-1):0] wen_test_inner;

  // bist start to work in IDLE
  reg rf_start;
  
  // compare the data read from sram with the data written into sram 
  // enable signal
  reg check_en;

  // bist test data source select signal
  // "pattern_sel == 1'b0"-----> test_pattern =  32'b0;
  // "pattern_sel == 1'b1"-----> test_pattern =  32'b1;
  reg pattern_sel;
  wire [(DATA_WIDTH-1):0] test_pattern;
  reg [4:0] cstate, nstate;
  // 1 -- address is goign upward; 0 -- address is going downward
  reg up1_down0; 
  // 1 -- address is stepping; 0 -- address remains
  reg count_en;  

  //-----------------------------------------------------------------
  //     Combinatorial portion
  //-----------------------------------------------------------------
  assign b_done = r_end;
  assign test_pattern = (pattern_sel == 1'b0) ? {DATA_WIDTH{1'b0}} : {DATA_WIDTH{1'b1}};

  //--------------------------------------------------------------------
  // The output values of all the mux below will be changed based on the
  // sram whether in normal operation or in bist test mode. 
  //---------------------------------------------------------------------
  assign data_test = (b_te == 1'b1) ? test_pattern   : data_fun;
  assign addr_test = (b_te == 1'b1) ? test_addr      : addr_fun;
  assign wen_test  = (b_te == 1'b1) ? wen_test_inner : wen_fun;
  assign cen_test  = (b_te == 1'b1) ? 1'b0           : cen_fun;
  assign oen_test  = (b_te == 1'b1) ? 1'b0           : oen_fun;

  //--------------------------------------------------------------------
  //    Sequential portion
  //--------------------------------------------------------------------

  //--------------------------------
  // Generate bist work end signal. 
  //--------------------------------
  always @(posedge b_clk , negedge b_rst_n) begin
    if (b_rst_n == 1'b0) 
       r_end<=1'b0;
    else if (r_end_en == 1'b1) 
       r_end<= 1'b1;
       else
         r_end <= 1'b0;
  end
  //----------------------------------------------------
  //          Generate the sram test address.
  // "test_addr_rst " and "up1_down0" decide the mode of 
  // variable the address(increment/decrement). 
  //-----------------------------------------------------
  always @(posedge b_clk , negedge b_rst_n) begin
    if (b_rst_n == 1'b0) 
       test_addr <= {ADDR_WIDTH{1'b0}};
    else if (b_te == 1'b1) 
  	  if (test_addr_rst == 1'b1) 
           if (up1_down0 == 1'b1)
          	  test_addr<=  {ADDR_WIDTH{1'b0}};
           else
              test_addr<=  {ADDR_WIDTH{1'b1}};
     	else
           if (count_en == 1'b1)
               if (up1_down0 == 1'b1)
          	      test_addr<=  test_addr + 1'b1;
               else
                  test_addr<=  test_addr - 1'b1;
  end

  always @(posedge b_clk , negedge b_rst_n)
    if (b_rst_n == 1'b0) 
       b_fail<=1'b1;
    else begin
      //---------------------------------------------------------
      //  When in bist idle1 state, "b_fail" defualt value is "0".
      // --------------------------------------------------------
      if ((b_te == 1'b1) && (rf_start == 1'b1))
          b_fail<=  1'b0;

      //------------------------------------------------------------
      //  "b_fail" value is "1", when data read from sram is different
      // from the expected data wirtten into sram.
      //--------------------------------------------------------------
      if ((b_te == 1'b1) && (check_en == 1'b1) && !(test_pattern == ram_read_out))
          b_fail<=  1'b1;
     end
  
  //------------------------------------------------------------------------------
  //                    Bist test state machine
  //   write "0"(initial sram)                         test_address 0-->1fff
  //   read  "0"------> compare -------->write "1"     test_address 1fff-->0
  //   read  "1"------> compare -------->write "0"     test_address 0-->1fff
  //   write "1"------> read "1"-------->compare       test_address 1fff-->0        
  //   write "0"------> read "0"-------->compare       test_address 0-->1fff        
  //   write "1"------> read "1"-------->compare       test_address 1fff-->0        
  //   write "0"------> read "0"-------->compare       test_address 0-->1fff        
  //------------------------------------------------------------------------------
  always @(posedge b_clk , negedge b_rst_n) begin
    if (b_rst_n == 1'b0) 
          cstate<=`IDEL1;
    else
          cstate<= nstate;
  end
  
  always @(cstate or b_te or r_end or test_addr) begin
    up1_down0     = 1'b1;
    count_en      = 1'b0;
    r_end_en      = 1'b0;
    pattern_sel   = 1'b0;
    test_addr_rst = 1'b0;
    rf_start      = 1'b0;
    check_en      = 1'b0;
    wen_test_inner = {WE_WIDTH{1'b1}};
    nstate        = cstate;
    case (cstate)
      `IDEL1 :
          begin
             test_addr_rst = 1'b1;
             if (b_te == 1'b1 && r_end == 1'b0) begin
                   nstate   = `P1_WRITE0;
                   rf_start = 1'b1;
             end
          end
      `P1_WRITE0 :   //initial sram from addr 0~1fff
          begin
    	    count_en       = 1'b1;
    	    wen_test_inner = {WE_WIDTH{1'b0}};
    	    pattern_sel    = 1'b0;
             if (test_addr == {ADDR_WIDTH{1'b1}} ) begin
                  nstate        = `IDEL2;
                  test_addr_rst = 1'b1;
    	            up1_down0     = 1'b0;
             end
          end
      `IDEL2 :
          begin
    	      pattern_sel   = 1'b0;
    	      up1_down0     = 1'b0;
            test_addr_rst = 1'b1; 
            nstate        = `P2_READ0;
          end
      `P2_READ0 :
          begin
            nstate = `P2_COMPARE0;
          end
      `P2_COMPARE0 :  //compare all "0" data after read from addr 0~1fff
          begin
             pattern_sel = 1'b0;
    	       check_en    = 1'b1;
             nstate      = `P2_WRITE1;
          end
      `P2_WRITE1 :  //all "1" write test from addr 1fff~0
          begin
    	      up1_down0      = 1'b0;
    	      count_en       = 1'b1;
    	      wen_test_inner = {WE_WIDTH{1'b0}};
    	      pattern_sel    = 1'b1;
             if (test_addr == {ADDR_WIDTH{1'b0}}) begin
                  nstate        = `IDEL3;
                  test_addr_rst = 1'b1;
    	          up1_down0     = 1'b1;
             end
             else
                nstate        = `P2_READ0;
          end
      `IDEL3 :
          begin
             pattern_sel   = 1'b1;
             test_addr_rst = 1'b1;
             nstate        = `P3_READ1;
          end
      `P3_READ1 :
          begin
             nstate = `P3_COMPARE1;
          end
      `P3_COMPARE1 :  //compare all "1" data after read from addr 1fff~0
          begin
            pattern_sel = 1'b1;
            check_en    = 1'b1;
            nstate      = `P3_WRITE0;
          end
      `P3_WRITE0 :
          begin
             wen_test_inner = {WE_WIDTH{1'b0}};
             pattern_sel    = 1'b0;
             nstate         = `P3_READ0;
          end
      `P3_READ0 :
          begin
            nstate = `P3_COMPARE0;
          end
      `P3_COMPARE0 :
          begin
            pattern_sel = 1'b0;
            check_en    = 1'b1;
            nstate      = `P3_WRITE1;
          end
      `P3_WRITE1 :
          begin
             wen_test_inner = {WE_WIDTH{1'b0}};
             pattern_sel    = 1'b1;
             count_en       = 1'b1;
             if (test_addr == {ADDR_WIDTH{1'b1}}) begin
                  nstate        = `IDEL4;
                  test_addr_rst = 1'b1;
             end
             else
                nstate        = `P3_READ1;
          end
      `IDEL4 :   // read all data from addr 1fff~0 and compare with write data "1" every time 
          begin
            pattern_sel   = 1'b1;
            test_addr_rst = 1'b1;
            nstate        = `P4_READ1;
          end
      `P4_READ1 :
          begin
            nstate = `P4_COMPARE1;
          end
      `P4_COMPARE1 :
          begin
            pattern_sel = 1'b1;
            check_en    = 1'b1;
            nstate      = `P4_WRITE0;
          end
      `P4_WRITE0 :
          begin
            wen_test_inner = {WE_WIDTH{1'b0}};
            pattern_sel    = 1'b0;
            count_en       = 1'b1;
             if (test_addr == {ADDR_WIDTH{1'b1}}) begin
                   nstate        = `IDEL5;
                   test_addr_rst = 1'b1;
             end
             else         
                nstate        = `P4_READ1;
          end
      `IDEL5 :  // read all data from addr 1fff~0 and compare with write data "0" every time 
          begin
             pattern_sel   = 1'b1;
             test_addr_rst = 1'b1;
             nstate        = `P5_READ0;
          end
      `P5_READ0 :
          begin
             nstate = `P5_COMPARE0;
          end
      `P5_COMPARE0 :
          begin
             pattern_sel=1'b0;
             check_en=1'b1;
             nstate = `P5_WRITE1;
          end
      `P5_WRITE1 :
          begin
             wen_test_inner = {WE_WIDTH{1'b0}};
             pattern_sel   = 1'b1;
             nstate = `P5_READ1;
          end
      `P5_READ1 :
          begin
             nstate = `P5_COMPARE1;
          end
      `P5_COMPARE1 :
          begin
             pattern_sel=1'b1;
             check_en=1'b1;
             nstate = `P5_WRITE0;
          end
      `P5_WRITE0 :
          begin
             wen_test_inner = {WE_WIDTH{1'b0}};
             pattern_sel    = 1'b0;
             count_en       = 1'b1;
             if (test_addr == {ADDR_WIDTH{1'b1}}) begin
                   nstate        = `IDEL6;
                   test_addr_rst = 1'b1;
             end
             else
                nstate        = `P5_READ0;
          end
      `IDEL6 :
          begin
             pattern_sel   = 1'b0;
             test_addr_rst = 1'b1;
             nstate        = `P6_READ0;
          end
      `P6_READ0 :
          begin
             nstate        = `P6_COMPARE0;
          end
      `P6_COMPARE0 :
          begin
             pattern_sel = 1'b0;
             check_en    = 1'b1;
             count_en    = 1'b1;
             if (test_addr == {ADDR_WIDTH{1'b1}}) begin
                   nstate        = `IDEL1;
                   test_addr_rst = 1'b1;
                   r_end_en      = 1'b1;
             end
             else
                nstate = `P6_READ0;
          end
      default :
          begin
             nstate        = `IDEL1;
             test_addr_rst = 1'b1;
          end 
    endcase
  end

endmodule

RA1SH.v

module RA1SH ( //8K
   Q,
   CLK,
   CEN,
   WEN,
   A,
   D,
   OEN
);
   parameter		   BITS = 8;
   parameter		   word_depth = 8192;
   parameter		   addr_width = 13;
   parameter		   wordx = {BITS{1'bx}};
   parameter		   addrx = {addr_width{1'bx}};
	
   output [BITS-1:0] Q;
   input CLK;
   input CEN;
   input WEN;
   input [addr_width-1:0] A;
   input [BITS-1:0] D;
   input OEN;

   reg [BITS-1:0]	   mem [word_depth-1:0];

   reg			   NOT_CEN;
   reg			   NOT_WEN;

   reg			   NOT_A0;
   reg			   NOT_A1;
   reg			   NOT_A2;
   reg			   NOT_A3;
   reg			   NOT_A4;
   reg			   NOT_A5;
   reg			   NOT_A6;
   reg			   NOT_A7;
   reg			   NOT_A8;
   reg			   NOT_A9;
   reg			   NOT_A10;
   reg			   NOT_A11;
   reg			   NOT_A12;
   reg [addr_width-1:0]	   NOT_A;
   reg			   NOT_D0;
   reg			   NOT_D1;
   reg			   NOT_D2;
   reg			   NOT_D3;
   reg			   NOT_D4;
   reg			   NOT_D5;
   reg			   NOT_D6;
   reg			   NOT_D7;
   reg [BITS-1:0]	   NOT_D;
   reg			   NOT_CLK_PER;
   reg			   NOT_CLK_MINH;
   reg			   NOT_CLK_MINL;

   reg			   LAST_NOT_CEN;
   reg			   LAST_NOT_WEN;
   reg [addr_width-1:0]	   LAST_NOT_A;
   reg [BITS-1:0]	   LAST_NOT_D;
   reg			   LAST_NOT_CLK_PER;
   reg			   LAST_NOT_CLK_MINH;
   reg			   LAST_NOT_CLK_MINL;


   wire [BITS-1:0]   _Q;
   wire			   _OENi;
   wire [addr_width-1:0]   _A;
   wire			   _CLK;
   wire			   _CEN;
   wire			   _OEN;
   wire                    _WEN;

   wire [BITS-1:0]   _D;
   wire                    re_flag;
   wire                    re_data_flag;


   reg			   LATCHED_CEN;
   reg	                   LATCHED_WEN;
   reg [addr_width-1:0]	   LATCHED_A;
   reg [BITS-1:0]	   LATCHED_D;

   reg			   CENi;
   reg           	   WENi;
   reg [addr_width-1:0]	   Ai;
   reg [BITS-1:0]	   Di;
   reg [BITS-1:0]	   Qi;
   reg [BITS-1:0]	   LAST_Qi;



   reg			   LAST_CLK;





   task update_notifier_buses;
   begin
      NOT_A = {
               NOT_A12,
	       NOT_A11,
               NOT_A10,
               NOT_A9,
               NOT_A8,
               NOT_A7,
               NOT_A6,
               NOT_A5,
               NOT_A4,
               NOT_A3,
               NOT_A2,
               NOT_A1,
               NOT_A0};
      NOT_D = {
               NOT_D7,
               NOT_D6,
               NOT_D5,
               NOT_D4,
               NOT_D3,
               NOT_D2,
               NOT_D1,
               NOT_D0};
   end
   endtask

   task mem_cycle;
   begin
      casez({WENi,CENi})

	2'b10: begin
	   read_mem(1,0);
	end
	2'b00: begin
	   write_mem(Ai,Di);
	   read_mem(0,0);
	end
	2'b?1: ;
	2'b1x: begin
	   read_mem(0,1);
	end
	2'bx0: begin
	   write_mem_x(Ai);
	   read_mem(0,1);
	end
	2'b0x,
	2'bxx: begin
	   write_mem_x(Ai);
	   read_mem(0,1);
	end
      endcase
   end
   endtask
      

   task update_last_notifiers;
   begin
      LAST_NOT_A = NOT_A;
      LAST_NOT_D = NOT_D;
      LAST_NOT_WEN = NOT_WEN;
      LAST_NOT_CEN = NOT_CEN;
      LAST_NOT_CLK_PER = NOT_CLK_PER;
      LAST_NOT_CLK_MINH = NOT_CLK_MINH;
      LAST_NOT_CLK_MINL = NOT_CLK_MINL;
   end
   endtask

   task latch_inputs;
   begin
      LATCHED_A = _A ;
      LATCHED_D = _D ;
      LATCHED_WEN = _WEN ;
      LATCHED_CEN = _CEN ;
      LAST_Qi = Qi;
   end
   endtask


   task update_logic;
   begin
      CENi = LATCHED_CEN;
      WENi = LATCHED_WEN;
      Ai = LATCHED_A;
      Di = LATCHED_D;
   end
   endtask



   task x_inputs;
      integer n;
   begin
      for (n=0; n<addr_width; n=n+1)
	 begin
	    LATCHED_A[n] = (NOT_A[n]!==LAST_NOT_A[n]) ? 1'bx : LATCHED_A[n] ;
	 end
      for (n=0; n<BITS; n=n+1)
	 begin
	    LATCHED_D[n] = (NOT_D[n]!==LAST_NOT_D[n]) ? 1'bx : LATCHED_D[n] ;
	 end
      LATCHED_WEN = (NOT_WEN!==LAST_NOT_WEN) ? 1'bx : LATCHED_WEN ;

      LATCHED_CEN = (NOT_CEN!==LAST_NOT_CEN) ? 1'bx : LATCHED_CEN ;
   end
   endtask

   task read_mem;
      input r_wb;
      input xflag;
   begin
      if (r_wb)
	 begin
	    if (valid_address(Ai))
	       begin
                     Qi=mem[Ai];
	       end
	    else
	       begin
		  Qi=wordx;
	       end
	 end
      else
	 begin
	    if (xflag)
	       begin
		  Qi=wordx;
	       end
	    else
	       begin
	          Qi=Di;
	       end
	 end
   end
   endtask

   task write_mem;
      input [addr_width-1:0] a;
      input [BITS-1:0] d;
 
   begin
      casez({valid_address(a)})
	1'b0: 
		x_mem;
	1'b1: mem[a]=d;
      endcase
   end
   endtask

   task write_mem_x;
      input [addr_width-1:0] a;
   begin
      casez({valid_address(a)})
	1'b0: 
		x_mem;
	1'b1: mem[a]=wordx;
      endcase
   end
   endtask

   task x_mem;
      integer n;
   begin
      for (n=0; n<word_depth; n=n+1)
	 mem[n]=wordx;
   end
   endtask

   task process_violations;
   begin
      if ((NOT_CLK_PER!==LAST_NOT_CLK_PER) ||
	  (NOT_CLK_MINH!==LAST_NOT_CLK_MINH) ||
	  (NOT_CLK_MINL!==LAST_NOT_CLK_MINL))
	 begin
	    if (CENi !== 1'b1)
               begin
		  x_mem;
		  read_mem(0,1);
	       end
	 end
      else
	 begin
	    update_notifier_buses;
	    x_inputs;
	    update_logic;
	    mem_cycle;
	 end
      update_last_notifiers;
   end
   endtask

   function valid_address;
      input [addr_width-1:0] a;
   begin
      valid_address = (^(a) !== 1'bx);
   end
   endfunction


   bufif0 (Q[0], _Q[0], _OENi);
   bufif0 (Q[1], _Q[1], _OENi);
   bufif0 (Q[2], _Q[2], _OENi);
   bufif0 (Q[3], _Q[3], _OENi);
   bufif0 (Q[4], _Q[4], _OENi);
   bufif0 (Q[5], _Q[5], _OENi);
   bufif0 (Q[6], _Q[6], _OENi);
   bufif0 (Q[7], _Q[7], _OENi);
   buf (_D[0], D[0]);
   buf (_D[1], D[1]);
   buf (_D[2], D[2]);
   buf (_D[3], D[3]);
   buf (_D[4], D[4]);
   buf (_D[5], D[5]);
   buf (_D[6], D[6]);
   buf (_D[7], D[7]);
   buf (_A[0], A[0]);
   buf (_A[1], A[1]);
   buf (_A[2], A[2]);
   buf (_A[3], A[3]);
   buf (_A[4], A[4]);
   buf (_A[5], A[5]);
   buf (_A[6], A[6]);
   buf (_A[7], A[7]);
   buf (_A[8], A[8]);
   buf (_A[9], A[9]);
   buf (_A[10], A[10]);
   buf (_A[11], A[11]);
   buf (_A[12], A[12]);
   buf (_CLK, CLK);
   buf (_WEN, WEN);
   buf (_OEN, OEN);
   buf (_CEN, CEN);


   assign _OENi = _OEN;
   assign _Q = Qi;
   assign re_flag = !(_CEN);
   assign re_data_flag = !(_CEN || _WEN);


   always @(
	    NOT_A0 or
	    NOT_A1 or
	    NOT_A2 or
	    NOT_A3 or
	    NOT_A4 or
	    NOT_A5 or
	    NOT_A6 or
	    NOT_A7 or
	    NOT_A8 or
	    NOT_A9 or
	    NOT_A10 or
	    NOT_A11 or
	    NOT_A12 or
	    NOT_D0 or
	    NOT_D1 or
	    NOT_D2 or
	    NOT_D3 or
	    NOT_D4 or
	    NOT_D5 or
	    NOT_D6 or
	    NOT_D7 or
	    NOT_WEN or
	    NOT_CEN or
	    NOT_CLK_PER or
	    NOT_CLK_MINH or
	    NOT_CLK_MINL
	    )
      begin
         process_violations;
      end

   always @( _CLK )
      begin
         casez({LAST_CLK,_CLK})
	   2'b01: begin
	      latch_inputs;
	      update_logic;
	      mem_cycle;
	   end

	   2'b10,
	   2'bx?,
	   2'b00,
	   2'b11: ;

	   2'b?x: begin
	      x_mem;
              read_mem(0,1);
	   end
	   
	 endcase
	 LAST_CLK = _CLK;
      end

   specify 
      $setuphold(posedge CLK, CEN, 1.000, 0.500, NOT_CEN);
      $setuphold(posedge CLK &&& re_flag, WEN, 1.000, 0.500, NOT_WEN);
      $setuphold(posedge CLK &&& re_flag, A[0], 1.000, 0.500, NOT_A0);
      $setuphold(posedge CLK &&& re_flag, A[1], 1.000, 0.500, NOT_A1);
      $setuphold(posedge CLK &&& re_flag, A[2], 1.000, 0.500, NOT_A2);
      $setuphold(posedge CLK &&& re_flag, A[3], 1.000, 0.500, NOT_A3);
      $setuphold(posedge CLK &&& re_flag, A[4], 1.000, 0.500, NOT_A4);
      $setuphold(posedge CLK &&& re_flag, A[5], 1.000, 0.500, NOT_A5);
      $setuphold(posedge CLK &&& re_flag, A[6], 1.000, 0.500, NOT_A6);
      $setuphold(posedge CLK &&& re_flag, A[7], 1.000, 0.500, NOT_A7);
      $setuphold(posedge CLK &&& re_flag, A[8], 1.000, 0.500, NOT_A8);
      $setuphold(posedge CLK &&& re_flag, A[9], 1.000, 0.500, NOT_A9);
      $setuphold(posedge CLK &&& re_flag, A[10], 1.000, 0.500, NOT_A10);
      $setuphold(posedge CLK &&& re_flag, A[11], 1.000, 0.500, NOT_A11);
      $setuphold(posedge CLK &&& re_data_flag, D[0], 1.000, 0.500, NOT_D0);
      $setuphold(posedge CLK &&& re_data_flag, D[1], 1.000, 0.500, NOT_D1);
      $setuphold(posedge CLK &&& re_data_flag, D[2], 1.000, 0.500, NOT_D2);
      $setuphold(posedge CLK &&& re_data_flag, D[3], 1.000, 0.500, NOT_D3);
      $setuphold(posedge CLK &&& re_data_flag, D[4], 1.000, 0.500, NOT_D4);
      $setuphold(posedge CLK &&& re_data_flag, D[5], 1.000, 0.500, NOT_D5);
      $setuphold(posedge CLK &&& re_data_flag, D[6], 1.000, 0.500, NOT_D6);
      $setuphold(posedge CLK &&& re_data_flag, D[7], 1.000, 0.500, NOT_D7);

      $period(posedge CLK, 3.000, NOT_CLK_PER);
      $width(posedge CLK, 1.000, 0, NOT_CLK_MINH);
      $width(negedge CLK, 1.000, 0, NOT_CLK_MINL);

      (CLK => Q[0])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[1])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[2])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[3])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[4])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[5])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[6])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (CLK => Q[7])=(1.000, 1.000, 0.500, 1.000, 0.500, 1.000);
      (OEN => Q[0])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[1])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[2])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[3])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[4])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[5])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[6])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
      (OEN => Q[7])=(1.000, 1.000, 1.000, 1.000, 1.000, 1.000);
   endspecify 

endmodule

后记

这是AHB-SRAM项目中,内部模块sram_core.v的所有文件,如果需要跳转到查看此项目的架构,请点击跳转
AHB-SRAM简单设计之架构图解

笔者是小白,自学输出过程中,难免有错误,请大家指正!

  • 13
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: ahb-sram指的是高级外围总线(AHB)和静态随机存储器(SRAM)之间的接口设计和验证。 AHB-SRAM设计验证主要关注于确保AHB总线和SRAM之间的通信正常和可靠。设计验证的过程包括以下几个关键步骤: 1. 规划设计验证策略:在开始验证之前,需要明确定义验证目标和计划。确定验证所需资源、验证方法和验证环境等。 2. 静态验证:进行静态验证以评估设计的一致性和正确性。这可以通过使用模拟和仿真工具来完成,以验证设计的逻辑功能是否符合规格要求。 3. 动态验证:通过建立高级仿真模型或使用硬件描述语言(HDL)编写测试程序,进行动态验证。这些测试程序模拟了实际使用AHB-SRAM接口的情况,验证了设计和实现是否能够正确地处理各种读写操作和异常情况。 4. 性能验证:通过使用性能评估工具和技术,测试和验证设计在处理大量数据时的吞吐量、延迟和带宽等性能指标。这有助于确保AHB-SRAM设计能够满足系统需求。 5. 集成验证:将AHB-SRAM设计与其他子系统和外设集成,验证设计在整个系统中的功能和性能。这涉及到集成测试和系统级仿真,以确保整个系统的一致性和稳定性。 6. 错误排查和调试:在设计验证过程中,可能会发现各种问题和错误。需要进行适当的排查和调试,以找出问题的原因,并修复设计中的错误。 通过上述步骤的设计验证过程,可以最大程度地确保AHB-SRAM设计在实际应用中的正确性和可靠性。这样可以提高系统的稳定性和性能,并降低后续开发和维护的风险和成本。 ### 回答2: AHB(SRAM)设计验证是对AHB(SRAM)的硬件设计进行验证的过程。AHB指的是高级外设总线(Advanced High-performance Bus),是一种用于处理器与外设之间的通信的总线协议。SRAM指的是静态随机存取存储器(Static Random-access Memory),是一种常见的计算机内存存储单元。 AHB-SRAM设计验证旨在确保这个硬件设计符合AHB协议,并能够正确地存储和读取数据。验证过程一般包括以下几个步骤: 1. 设计规划:确定设计验证的目标和范围,编写验证计划和验证测试案例。 2. 功能验证:通过对设计电路进行功能仿真,验证设计的各项功能是否满足需求。通过使用一些特定的设计验证工具,对设计电路进行输入和输出的模拟,以验证逻辑电路的正确性。 3. 性能验证:通过对设计电路进行性能仿真,验证设计的时序和时钟频率是否满足要求。通过模拟各种情况下的数据存储和读取操作,检测潜在的性能瓶颈。 4. 物理验证:通过对设计电路进行物理验证,验证设计的布局和连线是否符合物理设计规范和约束条件。通过使用专业的物理验证工具,检查电路中是否存在物理故障,如电气连接问题、时序冲突等。 5. 集成验证:将设计电路与其他相关组件进行集成,验证整个系统的功能和性能。 AHB-SRAM设计验证是一个非常关键的步骤,它能够检测和纠正设计中的错误和问题,确保最终设计的可靠性和稳定性。只有通过了验证的设计才能进行后续的制造和生产。同时,设计验证还能够提供设计改进和优化的反馈,以便进一步提高设计的性能和效果。 ### 回答3: AHB(SRAM)是一种特定类型的静态随机存取存储器设计,用于在系统总线上进行数据传输和存储。设计验证是确保设计的功能和性能符合规范和需求的过程。 AHB-SRAM设计验证的目标是验证AHB-SRAM的功能正确性、数据的一致性和性能方面的指标。验证过程通常包括以下几个步骤: 1. 功能验证:通过编写测试用例,验证AHB-SRAM在不同的读写操作下是否能够正确地读写数据。测试用例需要覆盖各种读写情况,包括随机读写、顺序读写等。同时还需要测试错误情况下的处理机制,比如写入冲突、读取无效地址等。通过功能验证可以确保AHB-SRAM能够按照规定的操作进行数据的读写。 2. 数据一致性验证:在多核系统中,多个处理器可能同时访问AHB-SRAM。数据一致性验证的目标是验证在多个处理器同时读写AHB-SRAM时,数据的一致性是否能够保持。验证过程中需要考虑读写操作的时序和数据同步机制,确保在多个处理器之间进行数据交换时不会出现数据冲突或数据丢失的情况。 3. 性能验证:AHB-SRAM的性能指标包括读写延迟和带宽。性能验证的目标是通过测试用例和性能评估工具来验证AHB-SRAM能够在规定的时钟周期内完成读写操作,并能够满足带宽需求。性能验证可以帮助确定系统中AHB-SRAM的使用限制和资源分配。 通过上述验证步骤,可以确保AHB-SRAM设计的正确性和性能符合预期。验证过程需要仔细设计测试用例和评估工具,同时需要对设计进行仿真和调试,以确保设计的稳定性和可靠性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰之行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值