AHB-SRAM简单设计之内部模块 sram_core.v
前言
他们都说这一部分不需要自己设计,还说了公司里面这部分都是买的,dft和bist前期就不用介入工作,因为买的IP里面已经集成进去了。如果公司没买IP,都是自己做的,那就需要前期和设计工程师一起交流,留下接口。
仅从设计层面来讲,sram_core.v的复杂程度也挺高的(仅针对小编小白)!所以,这部分打算直接附带码,先不做任何解释!如果后面还想分析,再附!
内部模块 sram_core.v
结合上面的图和下面的代码,理解:sram_core就是在里面例化了8片sram_bist
module sram_core(//input signalsinput 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 lowinput [3:0] bank0_csn, //两个bank,每个bank有四个片选input [3:0] bank1_csn,input bist_en, //BIST test modeinput dft_en, //DFT test mode//output signalsoutput [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 bank0assign bank0_bistdone = (bist_done3 && bist_done2) && (bist_done1 && bist_done0);//bist results of bank0assign bank0_bistfail = {bist_fail3,bist_fail2,bist_fail1,bist_fail0};//bist finishing state of bank1assign bank1_bistdone = (bist_done7 && bist_done6) && (bist_done5 && bist_done4);//bist results of bank1assign 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 signalsinput 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:readinput[12:0] sram_addr_in, input[7:0 ] sram_wdata_in,input bist_en, // MBIST modeinput dft_en, // DFT mode//output signalsoutput[7:0 ] sram_data_out, output bist_done, // 1: test overoutput 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 resultassign 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) beginif(!sram_rst_n)dft_data_r <= 0;else if(dft_en)dft_data_r <= dft_data;end//sram data outputassign 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 functionRA1SH 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 signalsinput b_clk, // bist clock input b_rst_n, // bist resetninput b_te, // bist enableinput [(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 signalsoutput [(ADDR_WIDTH-1):0] addr_test, // address of testoutput [(WE_WIDTH-1):0] wen_test, // writing control of bist test modeoutput cen_test, // chip enable control of bist test modeoutput oen_test, // output enable control of bist test modeoutput [(DATA_WIDTH-1):0] data_test, // data input of bist test modeoutput 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 modereg [(ADDR_WIDTH-1):0] test_addr;// bist test end signalreg 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 modereg [(WE_WIDTH-1):0] wen_test_inner;// bist start to work in IDLEreg rf_start;// compare the data read from sram with the data written into sram // enable signalreg 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 downwardreg up1_down0; // 1 -- address is stepping; 0 -- address remainsreg 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) beginif (b_rst_n == 1'b0) r_end<=1'b0;else if (r_end_en == 1'b1) r_end<= 1'b1;elser_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) beginif (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}};elsetest_addr<= {ADDR_WIDTH{1'b1}};elseif (count_en == 1'b1)if (up1_down0 == 1'b1)test_addr<= test_addr + 1'b1;elsetest_addr<= test_addr - 1'b1;endalways @(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) beginif (b_rst_n == 1'b0) cstate<=`IDEL1;elsecstate<= nstate;endalways @(cstate or b_te or r_end or test_addr) beginup1_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 :begintest_addr_rst = 1'b1;if (b_te == 1'b1 && r_end == 1'b0) beginnstate = `P1_WRITE0;rf_start = 1'b1;endend`P1_WRITE0 : //initial sram from addr 0~1fffbegincount_en = 1'b1;wen_test_inner = {WE_WIDTH{1'b0}};pattern_sel = 1'b0;if (test_addr == {ADDR_WIDTH{1'b1}} ) beginnstate = `IDEL2;test_addr_rst = 1'b1;up1_down0 = 1'b0;endend`IDEL2 :beginpattern_sel = 1'b0;up1_down0 = 1'b0;test_addr_rst = 1'b1; nstate = `P2_READ0;end`P2_READ0 :beginnstate = `P2_COMPARE0;end`P2_COMPARE0 : //compare all "0" data after read from addr 0~1fffbeginpattern_sel = 1'b0;check_en = 1'b1;nstate = `P2_WRITE1;end`P2_WRITE1 : //all "1" write test from addr 1fff~0beginup1_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}}) beginnstate = `IDEL3;test_addr_rst = 1'b1;up1_down0 = 1'b1;endelsenstate = `P2_READ0;end`IDEL3 :beginpattern_sel = 1'b1;test_addr_rst = 1'b1;nstate = `P3_READ1;end`P3_READ1 :beginnstate = `P3_COMPARE1;end`P3_COMPARE1 : //compare all "1" data after read from addr 1fff~0beginpattern_sel = 1'b1;check_en = 1'b1;nstate = `P3_WRITE0;end`P3_WRITE0 :beginwen_test_inner = {WE_WIDTH{1'b0}};pattern_sel = 1'b0;nstate = `P3_READ0;end`P3_READ0 :beginnstate = `P3_COMPARE0;end`P3_COMPARE0 :beginpattern_sel = 1'b0;check_en = 1'b1;nstate = `P3_WRITE1;end`P3_WRITE1 :beginwen_test_inner = {WE_WIDTH{1'b0}};pattern_sel = 1'b1;count_en = 1'b1;if (test_addr == {ADDR_WIDTH{1'b1}}) beginnstate = `IDEL4;test_addr_rst = 1'b1;endelsenstate = `P3_READ1;end`IDEL4 : // read all data from addr 1fff~0 and compare with write data "1" every time beginpattern_sel = 1'b1;test_addr_rst = 1'b1;nstate = `P4_READ1;end`P4_READ1 :beginnstate = `P4_COMPARE1;end`P4_COMPARE1 :beginpattern_sel = 1'b1;check_en = 1'b1;nstate = `P4_WRITE0;end`P4_WRITE0 :beginwen_test_inner = {WE_WIDTH{1'b0}};pattern_sel = 1'b0;count_en = 1'b1;if (test_addr == {ADDR_WIDTH{1'b1}}) beginnstate = `IDEL5;test_addr_rst = 1'b1;endelse nstate = `P4_READ1;end`IDEL5 : // read all data from addr 1fff~0 and compare with write data "0" every time beginpattern_sel = 1'b1;test_addr_rst = 1'b1;nstate = `P5_READ0;end`P5_READ0 :beginnstate = `P5_COMPARE0;end`P5_COMPARE0 :beginpattern_sel=1'b0;check_en=1'b1;nstate = `P5_WRITE1;end`P5_WRITE1 :beginwen_test_inner = {WE_WIDTH{1'b0}};pattern_sel = 1'b1;nstate = `P5_READ1;end`P5_READ1 :beginnstate = `P5_COMPARE1;end`P5_COMPARE1 :beginpattern_sel=1'b1;check_en=1'b1;nstate = `P5_WRITE0;end`P5_WRITE0 :beginwen_test_inner = {WE_WIDTH{1'b0}};pattern_sel = 1'b0;count_en = 1'b1;if (test_addr == {ADDR_WIDTH{1'b1}}) beginnstate = `IDEL6;test_addr_rst = 1'b1;endelsenstate = `P5_READ0;end`IDEL6 :beginpattern_sel = 1'b0;test_addr_rst = 1'b1;nstate = `P6_READ0;end`P6_READ0 :beginnstate = `P6_COMPARE0;end`P6_COMPARE0 :beginpattern_sel = 1'b0;check_en = 1'b1;count_en = 1'b1;if (test_addr == {ADDR_WIDTH{1'b1}}) beginnstate = `IDEL1;test_addr_rst = 1'b1;r_end_en = 1'b1;endelsenstate = `P6_READ0;enddefault :beginnstate = `IDEL1;test_addr_rst = 1'b1;end endcaseendendmodule
RA1SH.v
module RA1SH ( //8KQ,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;beginNOT_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};endendtasktask mem_cycle;begincasez({WENi,CENi})2'b10: beginread_mem(1,0);end2'b00: beginwrite_mem(Ai,Di);read_mem(0,0);end2'b?1: ;2'b1x: beginread_mem(0,1);end2'bx0: beginwrite_mem_x(Ai);read_mem(0,1);end2'b0x,2'bxx: beginwrite_mem_x(Ai);read_mem(0,1);endendcaseendendtasktask update_last_notifiers;beginLAST_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;endendtasktask latch_inputs;beginLATCHED_A = _A ;LATCHED_D = _D ;LATCHED_WEN = _WEN ;LATCHED_CEN = _CEN ;LAST_Qi = Qi;endendtasktask update_logic;beginCENi = LATCHED_CEN;WENi = LATCHED_WEN;Ai = LATCHED_A;Di = LATCHED_D;endendtasktask x_inputs;integer n;beginfor (n=0; n<addr_width; n=n+1)beginLATCHED_A[n] = (NOT_A[n]!==LAST_NOT_A[n]) ? 1'bx : LATCHED_A[n] ;endfor (n=0; n<BITS; n=n+1)beginLATCHED_D[n] = (NOT_D[n]!==LAST_NOT_D[n]) ? 1'bx : LATCHED_D[n] ;endLATCHED_WEN = (NOT_WEN!==LAST_NOT_WEN) ? 1'bx : LATCHED_WEN ;LATCHED_CEN = (NOT_CEN!==LAST_NOT_CEN) ? 1'bx : LATCHED_CEN ;endendtasktask read_mem;input r_wb;input xflag;beginif (r_wb)beginif (valid_address(Ai))beginQi=mem[Ai];endelsebeginQi=wordx;endendelsebeginif (xflag)beginQi=wordx;endelsebeginQi=Di;endendendendtasktask write_mem;input [addr_width-1:0] a;input [BITS-1:0] d;begincasez({valid_address(a)})1'b0: x_mem;1'b1: mem[a]=d;endcaseendendtasktask write_mem_x;input [addr_width-1:0] a;begincasez({valid_address(a)})1'b0: x_mem;1'b1: mem[a]=wordx;endcaseendendtasktask x_mem;integer n;beginfor (n=0; n<word_depth; n=n+1)mem[n]=wordx;endendtasktask process_violations;beginif ((NOT_CLK_PER!==LAST_NOT_CLK_PER) ||(NOT_CLK_MINH!==LAST_NOT_CLK_MINH) ||(NOT_CLK_MINL!==LAST_NOT_CLK_MINL))beginif (CENi !== 1'b1)beginx_mem;read_mem(0,1);endendelsebeginupdate_notifier_buses;x_inputs;update_logic;mem_cycle;endupdate_last_notifiers;endendtaskfunction valid_address;input [addr_width-1:0] a;beginvalid_address = (^(a) !== 1'bx);endendfunctionbufif0 (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 orNOT_A1 orNOT_A2 orNOT_A3 orNOT_A4 orNOT_A5 orNOT_A6 orNOT_A7 orNOT_A8 orNOT_A9 orNOT_A10 orNOT_A11 orNOT_A12 orNOT_D0 orNOT_D1 orNOT_D2 orNOT_D3 orNOT_D4 orNOT_D5 orNOT_D6 orNOT_D7 orNOT_WEN orNOT_CEN orNOT_CLK_PER orNOT_CLK_MINH orNOT_CLK_MINL)beginprocess_violations;endalways @( _CLK )begincasez({LAST_CLK,_CLK})2'b01: beginlatch_inputs;update_logic;mem_cycle;end2'b10,2'bx?,2'b00,2'b11: ;2'b?x: beginx_mem;read_mem(0,1);endendcaseLAST_CLK = _CLK;endspecify $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简单设计之架构图解
笔者是小白,自学输出过程中,难免有错误,请大家指正!
AHB-SRAM简单设计之内部模块 sram_core.v相关推荐
- AHB-SRAM简单设计之 顶层模块sram_top.v
前言 这部分就是顶层模块,直接将两个子模块例化并且连接端口就行了,直接看图施工! SRAM控制单元 sram_top.v module sramc_top(//input signalsinput w ...
- AHB-SRAM简单设计之架构图解
前言 还是慢慢来,比较快!在接触这个小项目时,就有种想法,吃透项目! 参考文章:基于AHB总线的sram控制器设计.AHB-SRAMC项目(结构图,核心代码.Testbench架构) 问:对于小白,该 ...
- 基于 AHB 总线的 SRAM 控制器设计
基于 AHB 总线的 SRAM 控制器设计 一.基于 AHB 的 sram 设计 1.总体设计框架 2.AHB总线传输协议 ①没有等待状态的单个读写操作 ②有等待状态的单个读写操作 ③连续读写操作 二 ...
- Launcher3 模块的简单设计
Launcher3 模块的简单设计 Lancher3 路劲: Z:\xxx\packages\apps\Launcher3 任务 1.AllApps背景透明化. 2.Allapps前3个图标变为Chr ...
- [译文]Domain Driven Design Reference(三)—— 模型驱动设计的构建模块
本书是Eric Evans对他自己写的<领域驱动设计-软件核心复杂性应对之道>的一本字典式的参考书,可用于快速查找<领域驱动设计>中的诸多概念及其简明解释. 其它本系列其它文章 ...
- 基于FPGA的USB2.0数据传输(通过本文可以自己设计USB2.0模块)
文章部分内容参考了相关论坛中的内容: 对文章中内容感兴趣或者有不懂的可以咨询QQ:2859340499 B站对应讲解本文视频链接 首先来说一下USB这个大家都知道的东西吧: USB通用串行总线,是应用 ...
- javascript框架设计之种子模块
javascript框架设计之种子模块 本文给大家介绍的是司徒正美的javascript框架设计的第二章种子模块的相关内容,算是一个小小的读后感,小伙伴们可以参考下. 种子模块也叫核心模块,是框架中最 ...
- 【解析】在设计软件的模块结构时,()不能改进设计质量
在设计软件的模块结构时,()不能改进设计质量: A.尽量减少高扇出结构 B.尽量减少高扇入结构 C.将具有相似功能的模块合并 D.完善模块的功能 解析: 在结构化设计中,系统由多个逻辑上相对独立的 ...
- 闲谈简单设计(KISS)疑惑
忙碌了一年了项目又到了交付了,虽然项目能成功上线(因为还有维护支持的团队).但是个人从技术上看,这是一个不那么成功的项目,因为后期艰难的修复bug,添加feature.这与简单设计有什么关系呢?在某模 ...
最新文章
- 第五周周记(国庆第一天)
- C# 特性(attribute)
- Python计算机视觉:第六章 图像聚类
- java爬虫框架动态_java爬虫框架webmagic
- Android 优化电池使用时间——根据需要操作广播接收器
- 百度代码规范 -- PHP
- python中的get函数_python之函数用法get()
- unity塔防游戏怪物转向_红包版塔防游戏合集-可以赚钱领红包的塔防游戏-无广告塔防游戏红包版大全...
- coreboot学习3:启动流程跟踪之bootblock阶段
- 顶会ICML特别开设“怼日”Workshop,意见不同您尽管来
- java中选择结构有哪些_Java中的选择结构
- spring batch(批处理)
- 第六章jQuery选择器
- MATLAB数据拟合中的若干问题(待续)
- 程序员看过都说好的资源网站,你懂得!
- 小米8的usb计算机连接不上,小米手机usb已连接电脑不显示怎么办
- Vue安装必要插件element-ui插件及axios依赖(详细)
- DirectX 开启硬件加速
- DELPHI关于汉字转拼音的一些想法
- C语言初阶(18) | 数组详解