精华内容
下载资源
问答
  • 简单双端口RAM设计(带下载链接) 1,设计需求 设计一个双端口的RAM,具有独立的读写时钟,独立读写地址和数据端口,具有复位功能,并具有读和写的使能信号。2,端口设计 写通道(write) Wrclk 输入端口 写通道的...

    简单双端口RAM设计(带下载链接)

    1,设计需求
    设计一个双端口的RAM,具有独立的读写时钟,独立读写地址和数据端口,具有复位功能,并具有读和写的使能信号。


    2,端口设计

    写通道(write)
    Wrclk 输入端口 写通道的时钟信号Aclear 输入端口 RAM复位信号Wren 输入端口 RAM写使能信号Wraddr[…]输入端口 RAM写数据的地址端口Wdata[…]输入端口 RAM的写数据端口
    读通道(read)
    Rdclk输入端口 读通道的时钟信号Rden 输入端口 读通道的使能信号Raddr[…] 输入端口 要读出的数据的地址信息Rdata[…]输出端口 读出的数据
    3,设计框图
     



    4,代码设计
    (1)参数定义
    数据宽度和地址宽度
     



    (2)输入输出端口
    各个信号的含义如第二小节所示。
     



    (3)双端口RAM定义

    定义了一个位宽为 data_width,深度为 2^addr_width 的ram存储器。

     



    4)在写时钟的驱动下,双端口RAM写数据以及复位功能设计
    在本写时钟下给出写地址和写数据,在下一个写时钟周期,数据被写入到RAM中。



    (5)再读时钟的驱动下,双端口RAM读数据的功能设计
    本读时钟给出读地址信息,在下一个读时钟信号,输出对应地址的数据。
     



    5,功能仿真(仿真代码
    (1)信号初始化,并复位
     



    (2)进行写数据仿真
    模拟产生写地址信息以及写数据,并使写使能信号有效。
    写地址和写数据在本时钟上升沿产生,并在下一个时钟的上升沿写入RAM中。
     



    (3)进行读数据仿真
    模拟产生读地址信号,并使读使能信号有效。
    读地址在本时钟上升沿产生,数据在下一个时钟的上升沿从RAM中读出。
     



    6,仿真波形
    (1)写数据过程的仿真波形
    可以看出,写地址和写数据在本时钟上升沿产生,并在下一个时钟的上升沿写入RAM中。
     


    (2)读数据过程的仿真波形
    可以看出,读地址在本时钟上升沿产生,数据在下一个时钟的上升沿从RAM中读出。
     




    7,源代码下载

    关注公众号“数字积木”,在公众号对话框内回复


    双端口RAM

    即可得到工程文件下载链接。

    本工程基于 Quartus 18.2 ,联合 Modelsim 进行功能仿真。

    展开全文
  • Verilog实现一个异步双端口ram,深度16,位宽8bit。A 口读出,B口写入。支持片选,读写请求,要求代码可综合。 module as_dul_RAM #( parameter addr_width = 4, parameter data_width = 8, parameter data_...

    用Verilog实现一个异步双端口ram,深度16,位宽8bit。A
    口读出,B口写入。支持片选,读写请求,要求代码可综合。

    module as_dul_RAM
    #(
        parameter addr_width = 4,
        parameter data_width = 8,
        parameter data_deepth = 16;
        )
    (
        input clka,
        input clkb,
        input rst_n,
        input cs,
        //wr
        input [addr_width - 1:0]wr_addr,
        input [data_width - 1:0]wr_data,
        input wr_en,
        //rd
        input [addr_width - 1:0]rd_addr,
        input rd_en,
        output reg [data_width - 1:0]rd_data
        );
    reg [data_width-1:0] register [data_deepth-1:0]    
    integer i;

    always@(posedge clka or negedge rst_n)
    begin
        if(!rst_n)begin
            for(i=1;i<data_deepth;i=i+1)
                register[i] <=8'b0000_0000;
            end
        else if(wr_en == 1 && cs == 1)
            register[wr_addr] <= wr_data;
        else
            register[wr_addr] <= register[wr_addr];
    end

    always@(posedge clkb or negedge rst_n)
    begin
        if(!rst_n)
            rd_data <= 0;
        else if(rd_en == 1 && cs == 1)
            rd_data <= register[rd_addr];
        else
            rd_data <= rd_data;
    end

    endmodule

            
    //仿真

    module as_dul_RAM_tb;
        reg clka;
        reg clkb;
        reg rst_n;
        //wr
        reg wr_addr;
        reg wr_data;
        reg wr_en;
        //rd
        reg rd_addr;
        wire rd_data;
        reg rd_en;
        
    as_dul_RAM u0(
        .clka(clka)
        .clkb(clkb),
        .rst_n(rst_n),
        
        .wr_addr(wr_addr),
        .wr_data(wr_data),
        .wr_en(wr_en),
        
        .rd_addr(rd_addr),
        .rd_data(rd_data),
        .rd_en(rd_en),
        );
        
    initial
    begin
        rst_n = 0;
        #10
        rst_n = 1;
        #1000;
    end

    initial
    begin
        clka = 0;
        clkb = 0;
        rd_en = 0;
        wr_en = 0;
        wr_addr = 0;
        wr_data = 0;
        rd_addr = 0;
        rd_data = 0;
    end

    always #10 clka = ~clka;
    always #15 clkb = ~clkb;
    //产生写数据
    initial begin
        #20;
        repeat(16) begin
            wr_data = wr_data + 1;
            #20;
        end
    end

    //产生读地址和写地址
    initial begin
        #20;
        repeat(16) begin
            wr_addr = wr_addr + 1;
            #20;
        end
        repeat(16) begin
            rd_addr = rd_addr + 1;
            #20;
        end
    end
    //产生使能信号
    initial begin
        wr_en = 1'b1;
        rd_en = 1'b0;
        #340
        wr_en = 1'b0;
        rd_en = 1'b1;
        #340
        wr_en = 1'b0;
        rd_en = 1'b0;
        #100;
    end
    endmodule

    展开全文
  • module Dual_RAM#( parameter DATA_WIDTH = 8, ADDR_WIDTH = 4 )( input wire sys_rst_n , input wire wr_clk , input wire rd_clk , input.
    module Dual_RAM#(
        parameter   DATA_WIDTH = 8,
                    ADDR_WIDTH = 4
    )(
        input   wire                        sys_rst_n   ,
        input   wire                        wr_clk      ,
        input   wire                        rd_clk      ,
        input   wire                        wr_en       ,  
        input   wire                        rd_en       ,
        input   wire    [DATA_WIDTH-1:0]    wr_data     ,
        input   wire    [ADDR_WIDTH-1:0]    wr_addr     ,
        input   wire    [ADDR_WIDTH-1:0]    rd_addr     ,
            
        output  reg     [DATA_WIDTH-1:0]    rd_data     
        );
    
    //定义存储器数组用于存储数据
    reg [DATA_WIDTH-1:0] RAM_MEN[0:2**ADDR_WIDTH - 1];
    
    //写数据
    parameter   RAM_LENGTH = 2**ADDR_WIDTH;
    integer i;
    always@(posedge wr_clk  or negedge  sys_rst_n)
        if(!sys_rst_n)
            for(i=0;i<RAM_LENGTH;i=i+1)
                RAM_MEN[i] <= 0;
        else    if(wr_en)    
            RAM_MEN[wr_addr] <= wr_data;
        else
            RAM_MEN[wr_addr] <= RAM_MEN[wr_addr];
    
    
    //读数据
    always@(posedge rd_clk  or negedge  sys_rst_n)
        if(!sys_rst_n)
            rd_data <= 0;
        else    if(rd_en)    
            rd_data <= RAM_MEN[rd_addr];
        else
            rd_data <= 0;
    
    
      
    endmodule

    testbench:

    module tb_Dual_RAM();
    
    parameter DATA_WIDTH = 8,
              ADDR_WIDTH = 4;  
    
    reg                        sys_rst_n ; 
    reg                        wr_clk    ;
    reg                        rd_clk    ;
    reg                        wr_en     ;
    reg                        rd_en     ;
    reg    [DATA_WIDTH-1:0]    wr_data   ;
    reg    [ADDR_WIDTH-1:0]    wr_addr   ;
    reg    [ADDR_WIDTH-1:0]    rd_addr   ;
    
    wire   [DATA_WIDTH-1:0]    rd_data  ;
    
    initial begin
        sys_rst_n = 0;
        wr_clk = 0;
        rd_clk = 0;
        wr_en = 0;
        rd_en = 0;
        wr_data = 8'd0;
        wr_addr = 4'd0;
        rd_addr = 4'd0;
        #20 sys_rst_n = 1;
        
        wr_data = 8'd4;
        #20 wr_en = 1;  wr_addr = 4'd0;
        #20             wr_addr = 4'd1;
        #20             wr_addr = 4'd2;
        wr_data = 8'd15;
        #20             wr_addr = 4'd3;
        #20             wr_addr = 4'd15;
        #20 wr_en = 0;  rd_en = 1;  rd_addr = 4'd1;
        #70             rd_addr = 4'd15;
    end
    
    always #10 wr_clk = ~wr_clk;
    always #20 rd_clk = ~rd_clk;
    
        
    Dual_RAM#(
        .DATA_WIDTH(DATA_WIDTH),
        .ADDR_WIDTH(ADDR_WIDTH)
    )    
    Dual_RAM_inst
    (
        .sys_rst_n (  sys_rst_n ) ,
        .wr_clk    (  wr_clk    ) ,
        .rd_clk    (  rd_clk    ) ,
        .wr_en     (  wr_en     ) ,  
        .rd_en     (  rd_en     ) ,
        .wr_data   (  wr_data   ) ,
        .wr_addr   (  wr_addr   ) ,
        .rd_addr   (  rd_addr   ) ,
    
        .rd_data   (  rd_data   ) 
        );
        
    endmodule

    仿真波形:

    展开全文
  • 二、双端口RAM原理及实现 1.原理 2.Verilog实现 3.优缺点分析 三、同步FIFO原理及实现 1.原理 2.Verilog实现 3.优缺点分析 四、异步FIFO原理及实现 1.原理 2.Verilog实现 3.优缺点分析 ...

    目录​​​​​​​

    一、单端口RAM原理及实现

    1.1、原理

    1.2、Verilog实现

    1.3、优缺点分析

    2、双端口RAM原理及实现

    2.1、原理

    2.2、Verilog实现

     2.3、优缺点分析

    3、 同步FIFO

    3.1、原理

    3.2、Verilog实现(1)

    3.3、Verilog实现(2)

    3.4、优缺点分析

    利用factor来记数当前FIFO中的数据量来判断空满

    利用位置指针多加1bit来判断空满

    4、异步FIFO

    4.1、原理

    4.2、格雷码

    4.3、Verilog代码实现

    4.4 、优缺点分析

    总结


    一、单端口RAM原理及实现

    1.1、原理

    在内存空间中开辟出一段固定大小的内存用于存储数据,每一个数据所占的bit位称之为位宽,这段内存空间中数据的总数称之为深度。例如reg [7:0] mem [255:0],这段内存空间中每一个数据的位宽为8bit,深度为256。

    在这段内存空间中,每个数据分配给一个地址,如上例深度为256,可以用8bit的地址来表示所有的数据,0000_0000则表示第0个数据,1111_1111则表示第255个数据。

    外部信号通过固定的时钟节拍,通过使能信号及地址信号来读取RAM中特定位置的数据或者向RAM中特定位置写入数据。

    1.2、Verilog实现

    module Single_Port_RAM
    (
    	//system input
    	 input 		clk
    	,input		rst_n
    	
    	//data input
    	,input 						enable_wr		//allow the user to read or write the data
    														//when enable_wr == 0,it means to write the data from RAM
    														//when enable_wr == 1,it means to read the data from RAM
    	,input		 	[7:0]		data_write
    	,input			[7:0]		address
    	
    	//data output
    	,output	reg 	[7:0]		data_read
    );
    
    //setup RAM which has the width of 8 and depth of 256
    localparam 	mem_width = 7;
    localparam	mem_depth = 255;
    reg	[mem_width:0]		mem	[mem_depth:0];
    
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		data_read <= 8'd0;
    	else if (!enable_wr)
    		mem[address] <= data_write;
    	else if (enable_wr)
    		data_read <= mem[address];
    end
    endmodule
    

    1.3、优缺点分析

    缺点:单一时刻只能进行读操作或者写操作,而不能同时进行;地址处的数据为0时也会读取,可能会发生错误。

    优点:简单,不需要协调读写操作;

    2、双端口RAM原理及实现

    2.1、原理

    参考如上的单端口RAM,双端口RAM在单端口RAM的基础上,将使能信号分为读使能信号和写使能信号,将地址信号分为读地址信号和写地址信号。

    2.2、Verilog实现

    module Dual_Port_RAM
    (
    	//system input
    	 input			clk
    	,input			rst_n
    	
    	//signal of read
    	,input						read_en				//when read_en == 1,read the data from mem according to read_addr
    	,input			[7:0]		read_addr
    	,output	reg 	[7:0]		read_data
    	
    	//signal of write
    	,input						write_en				//when write_en ==1,write the data to mem according to write_addr
    	,input			[7:0]		write_addr
    	,input			[7:0]		write_data
    );
    
    //setup RAM which has the width of 8 and depth of 256
    localparam 	mem_width = 7;
    localparam	mem_depth = 255;
    reg	[mem_width:0]		mem	[mem_depth:0];
    reg	[7:0]		i;
    
    always @ (posedge clk or negedge rst_n)
    begin
    	if (~rst_n)
    		for (i=0;i<=(mem_depth);i=i+1)
    			mem[i] <= 8'd0;
    	else if (write_en)
    		mem[write_addr] <= write_data;
    end
    
    always @ (posedge clk or negedge rst_n)
    begin
    	if (~rst_n)
    		read_data <= 8'd0;		
    	else if (read_en)									
    		read_data <= mem[read_addr];
    	else
    		read_data <= read_data;				//when read_en is disabled, read_data maintains the data before 	
    end
    endmodule

     2.3、优缺点分析

    优点:可以同时对RAM进行读写操作

    3、 同步FIFO

    3.1、原理

    在双端口RAM的基础上增加了一个限制项:即最先写进去的数据被最先读出来,此时不再对RAM的固定地址进行读写操作,而是按照写入顺序进行读出。

    同步FIFO主要用于①同一时钟域但是速度不同的模块之间充当buffer的功能;②用于不同数据宽度的模块之间,作为数据匹配(如前一个模块位宽为8bit,后一个模块为16bit,中间加一个FIFO,则每次读出两个数据进入后一级)

    按顺序写入和读出就会衍生出两个限制:RAM为空时不允许读出,RAM已经满后不允许写入。因此针对同步FIFO的难点主要在这儿。

    设置两个位置指针,其中一个指向下一次要写入数据的位置write_addr,另外一个指向本次要读取数据的位置read_addr,每次读写一次数据write_addr和read_addr各增加一,当二者均等于RAM深度时,下一次置零,重新计数。(相当于两个人从一楼到顶楼,然后跳下来接着往上走。)

    针对以上难点,出现了两种解决问题的方式:

    ①设定一个factor选项,每次写入数据,factor+1,;每次读出数据,factor-1。若此CLK有效边沿既要写入数据,又要读出数据,则Factor不变。则当factor的大小等于0时,表示RAM为空;当factor的大小等于RAM深度时,表示RAM为满;

    3.2、Verilog实现(1)

    //--==============================================================================
    // THIS FILE DESCRIBE A SYNCHRONIZATION FIFO (FIRST IN FIRST OUT)
    //	USING DATA COUNT TO DETECT FIFO FULL OR FIFO EMPTY 
    //
    // Project			:		Verilog_Learning
    // File_name		:		Sync_FIFO_1.v
    // Creator(s)		:		Moshang
    // Date				:		2020/09/29
    // Description		:		A synchronization FIFO control
    //
    // Modification	:
    //		(1) Initial Design 2020/09/29
    //
    //
    //--==============================================================================
    
    module Sync_FIFO_1
    (
    	//System input
    	 clk
    	,rst_n
    		
    	//read control
    	,fifo_read_en
    	,fifo_read_data
    	,fifo_read_err
    	,fifo_empty
    	
    	//write control
    	,fifo_write_en
    	,fifo_write_data
    	,fifo_write_err
    	,fifo_full
    	
    	//data count in mem
    	,fifo_data_cnt
    );
    
    // PARAMETER DECLARATION
    parameter 	FIFO_DATA_WIDTH	=	8;
    parameter	FIFO_ADDR_WIDTH	=	4;
    
    
    // INPUT AND OUTPUT DECLARATION
    input													clk;						//SYSTEM CLOCK INPUT 
    input													rst_n;					//SYSTEM RESET (RESET:	0)				
    input													fifo_read_en;			//FIFO READ ENABLE (ENABLE:	1)
    output		reg	[FIFO_DATA_WIDTH-1:0]	fifo_read_data;		//DATA READ FROM FIFO
    output		wire									fifo_read_err;			//FIFO IS EMPTY BUT READ IS ENABLED(ERR:	1)
    output		wire									fifo_empty;				//FIFO IS EMPTY(EMPTY:	1)
    input													fifo_write_en;			//FIFO WRITE ENABLE(ENABLE:	1)
    input					[FIFO_DATA_WIDTH-1:0]	fifo_write_data;		//DATR WRITE TO FIFO
    output		wire									fifo_write_err;		//FIFO IS FULL BUT WIRTE IS ENABLED(ERR:	1)
    output		wire									fifo_full;				//FIFO IS FULL(FULL:	1)
    output		reg	[FIFO_ADDR_WIDTH  :0]	fifo_data_cnt;			//FIFO DATA COUNT
    
    // INNER DECLARATION
    reg					[FIFO_ADDR_WIDTH-1:0]	fifo_read_addr;		//FIFO ADDR WHICH IS GOING TO WRITE DATA NEXT TIME
    reg					[FIFO_ADDR_WIDTH-1:0]	fifo_write_addr;		//FIFO ADDR WHICH IS READ DATA FROM NEXT TIME
    
    //FIFO MEMORY INSTANCE
    reg		[FIFO_DATA_WIDTH-1:0]	FIFO_MEM		[{(FIFO_ADDR_WIDTH){1'b1}}:0];
    integer 	i;
    
    
    //--=========================== MODULE SOURCE CODE ===========================--
    
    //--===========================================--
    // SRAM INSTANCE :
    // FIFO Rdata & FIFO Wdata
    //--===========================================--
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_read_data <= {(FIFO_DATA_WIDTH){1'b0}};
    	else if (fifo_read_en && (!fifo_empty))
    		fifo_read_data <= FIFO_MEM[fifo_read_addr];
    	else 
    		fifo_read_data <= fifo_read_data;
    end
    
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		for (i=0;i<=({(FIFO_ADDR_WIDTH){1'b1}});i=i+1)
    			begin
    				FIFO_MEM[i] <= {(FIFO_DATA_WIDTH){1'b0}};
    			end
    	else if (fifo_write_en && (!fifo_full))
    		FIFO_MEM[fifo_write_addr] <= fifo_write_data;
    	else
    		FIFO_MEM[fifo_write_addr] <= FIFO_MEM[fifo_write_addr];
    end
    
    //--===========================================--
    // READ ADDR & WRITE ADDR CONTROL
    //--===========================================--
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_read_addr <= {(FIFO_ADDR_WIDTH){1'b0}};
    	else if (fifo_read_en && (!fifo_empty))
    		fifo_read_addr <= fifo_read_addr + 1'b1;
    	else
    		fifo_read_addr <= fifo_read_addr;
    end
    
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_write_addr <= {(FIFO_ADDR_WIDTH){1'b0}};
    	else if (fifo_write_en && (!fifo_full))
    		fifo_write_addr <= fifo_write_addr + 1'b1;
    	else
    		fifo_write_addr <= fifo_write_addr;
    end
    
    //--===========================================--
    // FIFO DATA CNT
    //	VALID WRITE ONLY, DATA COUNT INCREASE
    // VALID READ ONLY , DATA COUNT DECREASE
    //--===========================================--
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_data_cnt <= {(FIFO_ADDR_WIDTH + 1'b1){1'b0}};
    	else if (fifo_read_en && (!fifo_empty) && (!(fifo_write_en && (!fifo_full))))			//FIFO VALID READ ONLY , COUINT DECREASE
    		fifo_data_cnt <= fifo_data_cnt - 1'b1;
    	else if (!(fifo_read_en && (!fifo_empty)) && (fifo_write_en && (!fifo_full)))			//FIFO VALID WRITE ONLY, COUNT INCREASE
    		fifo_data_cnt <= fifo_data_cnt + 1'b1;
    	else
    		fifo_data_cnt <= fifo_data_cnt;
    end
    
    //--===========================================--
    // FIFO DATA CNT
    // EMPTY, FULL , READ_ERR,WRITE_ERR
    // 因为fifo_data_cnt的增减是以空满信号为判断依据的,反过来,空满信号也是以fifo_data_cnt作为判断依据的,因此可以理解为互相驱动;
    // 且二者之间必须是实时响应的,如果两个都用always块来进行赋值,则二者之间会出现一个时钟周期的延迟,最终导致逻辑错误
    // 如果不想要这个延迟,则将其中一个作为assign类型来处理就可以
    //--===========================================--
    assign fifo_empty = 	(fifo_data_cnt == 0) & (rst_n);
    assign fifo_full 	=	(fifo_data_cnt == {1'b1,{(FIFO_ADDR_WIDTH){1'b0}}}) & (rst_n);
    
    assign fifo_read_err 	= (fifo_empty & fifo_read_en) & (rst_n); 
    assign fifo_write_err 	= (fifo_full & fifo_write_en) & (rst_n);
    
    endmodule
    
    

    ②在addr前面再加一bit标示位来标识是否已经转了一圈了来判决究竟是空还是满。

    当write_addr == read_addr时,可能是已经读操作赶上了写操作,即当前RAM为空;也可能是写操作已经转了一圈了到达读操作的位置,即RAM当前已经满了。在addr前面再加一bit标示位来标识是否已经转了一圈了来判决究竟是空还是满,正常逻辑情况下,写操作永远领先于读操作。如果最高位不同,而其他位相同,则说明写操作已经领先于读操作一圈,则FIFO状态为满;如果最高位相同,其他位也相同,则说明二者处于同一圈的同一位置,则FIFO状态为空)

    3.3、Verilog实现(2)

    //--==============================================================================
    // THIS FILE DESCRIBE A SYNCHRONIZATION FIFO (FIRST IN FIRST OUT)
    //	USING EXTRA BIT OF WRITE_ADDR AND READ_ADDR TO DETECT FIFO FULL AND FIFO EMPTY
    //
    // Project			:		Verilog_Learning
    // File_name		:		Sync_FIFO_2.v
    // Creator(s)		:		Moshang
    // Date				:		2020/09/29
    // Description		:		A synchronization FIFO control
    //
    // Modification	:
    //		(1) Initial Design 2020/09/29
    //
    //
    //--==============================================================================
    
    
    module Sync_FIFO_2
    (
    	//System input
    	 clk
    	,rst_n
    		
    	//read control
    	,fifo_read_en
    	,fifo_read_data
    	,fifo_read_err
    	,fifo_empty
    	
    	//write control
    	,fifo_write_en
    	,fifo_write_data
    	,fifo_write_err
    	,fifo_full	
    );
    
    // PARAMETER DECLARATION
    parameter FIFO_DATA_WIDTH 	= 	8;
    parameter FIFO_ADDR_WIDTH	= 	3;
    
    // INPUT DECLARATION
    input														clk;						// SYSTEM CLOCK INPUT 
    input														rst_n;					// SYSTEM RESET (RESET:1)
    input														fifo_read_en;			//	FIFO READ ENABLE (ENABLE:1)
    input														fifo_write_en;			// FIFO WRITE ENABLE (ENABLE:1)
    input			wire	[FIFO_DATA_WIDTH-1'b1 : 0]	fifo_write_data;		// DATA WRITE TO FIFO
    
    // OUTPUT DECLARATION
    output 		reg	[FIFO_DATA_WIDTH-1'b1 : 0]	fifo_read_data;		// DATA READ FROM FIFO
    output													fifo_read_err;			// ERR CAUSED WHEN FIFO IS EMPTY BUT READ IS DESIRED
    output													fifo_empty;				// FIFO EMPTY (EMPTY:1)
    output													fifo_write_err;		//	ERROR CAUSED WHEN FIFO IS FULL BUT WIRTE IS DESIRED
    output 													fifo_full;				// FIFO FULL (FULL:1)
    
    // FIFO MEMORY DECLARATION
    reg	[FIFO_DATA_WIDTH-1'b1:0]  	FIFO_MEM		[{(FIFO_ADDR_WIDTH){1'b1}} : 0];
    integer i;
    
    // WRITE ADDRESS AND READ ADDRESS DECLARATION
    // WHERE FIFO_READ_ADDR AND FIFO_WRITE_ADDR IS ONE BIT MORE THAN FIFO_ADDR_WIDTH
    reg 	[FIFO_ADDR_WIDTH : 0]	fifo_read_addr;
    reg 	[FIFO_ADDR_WIDTH : 0]	fifo_write_addr;
    
    //--========================== MODULE SOURCE CODE ============================--
    
    //--==================================--
    // SRAM INSTANCE 
    // FIFO READ DATA & FIFO WRITE DATA
    //--==================================--
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_read_data <= {(FIFO_DATA_WIDTH){1'b0}};
    	else if (fifo_read_en && (!fifo_empty) )
    		fifo_read_data <= FIFO_MEM[{fifo_read_addr[(FIFO_ADDR_WIDTH - 1'b1) : 0]}];
    	else
    		fifo_read_data <= fifo_read_data;
    end
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		for (i=0;i<={(FIFO_ADDR_WIDTH){1'b1}};i=i+1)
    			FIFO_MEM[i] <= {(FIFO_DATA_WIDTH){1'b0}};
    		else if (fifo_write_en && (!fifo_full))
    			FIFO_MEM[{fifo_write_addr[(FIFO_ADDR_WIDTH - 1'b1) : 0]}] <= fifo_write_data;
    		else 
    			FIFO_MEM[{fifo_write_addr[(FIFO_ADDR_WIDTH - 1'b1) : 0]}] <= FIFO_MEM[{fifo_write_addr[(FIFO_ADDR_WIDTH - 1'b1) : 0]}];
    end
    
    
    // FIFO CONTROL OF WRITE ADDRESS AND READ ADDRESS
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_read_addr <= {(FIFO_ADDR_WIDTH + 1'b1){1'b0}};
    	else if (fifo_read_en && (!fifo_empty) )
    		fifo_read_addr <= fifo_read_addr + 1'b1;
    	else
    		fifo_read_addr <= fifo_read_addr;
    end
    always @ (posedge clk or negedge rst_n)
    begin
    	if (!rst_n)
    		fifo_write_addr <= {(FIFO_ADDR_WIDTH + 1'b1){1'b0}};
    	else if (fifo_write_en && (!fifo_full) )
    		fifo_write_addr <= fifo_write_addr + 1'b1;
    	else
    		fifo_write_addr <= fifo_write_addr;
    end
    
    // DECTION OF FIFO EMPTY AND FIFO FULL
    assign fifo_empty 		= ((fifo_read_addr == fifo_write_addr) && rst_n);
    assign fifo_read_err 	= ((fifo_empty && fifo_read_en) && rst_n);
    
    assign fifo_full		 	= (((fifo_write_addr - fifo_read_addr) == {1'b1,{(FIFO_ADDR_WIDTH){1'b0}}}) && rst_n);
    assign fifo_write_err 	= ((fifo_full && fifo_write_en) && rst_n);
      
    endmodule
    
    

     

    3.4、优缺点分析

    • 利用factor来记数当前FIFO中的数据量来判断空满

    优点:逻辑简单,便于理解,且能直接知道当前FIFO中的剩余数据量

    缺点:使用寄存器资源较多,代码量增加

    • 利用位置指针多加1bit来判断空满

    优点:代码量总体来说比上一个小,逻辑也较为简单;使用的寄存器资源较少

    缺点:无法准确知道当前FIFO中一共有多少个数

    4、异步FIFO

    4.1、原理

    由于读写时钟来自不同的时钟域,且复位信号也有可能来自另外一个时钟域,则有可能会产生以下问题

    ① 异步复位信号在读写时钟域分别产生亚稳态;

    ② 空满信号判断时产生亚稳态,如 判断空信号时,需要在“读时钟域”内采样写地址信号,并在此时钟域与读地址信号进行对比,判断是否为空;由于对写地址信号为跨时钟域采样,可能会产生亚稳态。满信号的判断也是如此;

    ③ 跨时钟域对读地址/写地址 进行采样时,可能会产生误判;如读地址正好处在从“0001”到"0010"的变化边沿上,其实此时有两个bit发生变化,而两个bit一般不会是同时变化的,总会有先后顺序,即有可能采集到“0001、0010、0000、0011”这四个状态中的某一个。从而使得读写地址产生误判;

     

    针对以上三种问题,分别做出了处理方式:

    ① 异步复位产生亚稳态

              解决方式:对异步复位信号进行同步化处理,即分别在读时钟域和写时钟域内进行异步复位同步释放的操作;

    ② 空满信号产生亚稳态

              解决方式:在读时钟域内对写地址进行两级触发器采样,这样可以降低亚稳态发生的概率;(两级触发器采样实质上就是对异步信号进行同步化处理,降低亚稳态发生的概率;复位信号的异步复位同步释放的操作本质上也是这样)

    ③ 读写地址采样时产生误判

            解决方式:对读写地址采用格雷码编码,使得每次变化时只有1bit发生变化;如从“0001(0001的格雷码)”到“0011(0010的格雷码)”,此时只有1bit发生变化,采样时只有可能是0011或0001;如果采集错误(本来是0011,结果采集到了0001),也仅仅是慢一个时钟周期而已,因为两个数是相邻的,直接跳转到其他意料之外的地址,也不会产生重大的逻辑错误。

    4.2、格雷码

    格雷码:通常我们的计数采用8421码,如0000表示0,0001表示1,0010表示2;格雷码其特点是相邻编码之间只有1bit发生变化,如0000表示0,0001表示1,0011表示2等,从8421码转化为格雷码的方法如下:

    方法1: 最高位(MSB)不变,其余每一位与其相邻的高一位进行亦或,从而得到格雷码;

    方法2:8421码右移1bit,最高为补0,然后此新的代码与原来的8421码求亦或,从而得到格雷码(两种方法本质上是一样的)

    4.3、Verilog代码实现

    //--===================================================================--
    // THIS FILE DESCRIBE A MODULE OF ASYNCHRONIZATION FIFO WHICH IS OFTEN USED IN 
    // CLOCK DOMAIN CROSSING
    // Project		:	Verilog_Learning 
    // File_name	:	Async_FIFO.v
    // Creator(s)	:	Moshang
    // Date			:	2020/09/30
    //	Description	:	a module of asynchronization FIFO
    //	Modification:
    //			(1)	Initial Design 2020/09/30
    //
    //
    //--===================================================================--
    
    module Async_FIFO
    (
    		 rst_n							//	[UNKNOW DOMAIN]
    		,FIFO_read_clk 				// [READ DOMAIN]
    		,FIFO_write_clk				//	[WRITE DOMAIN]
    		
    		,FIFO_read_en					// [READ DOMAIN]
    		,FIFO_read_err					// [READ DOMAIN]
    		,FIFO_read_data				// [READ DOMAIN]
    		
    		,FIFO_write_en					//	[WRITE DOMAIN]
    		,FIFO_write_err				//	[WRITE DOMAIN]
    		,FIFO_write_data				//	[WRITE DOMAIN]
    		
    		,FIFO_empty						//	[READ DOMAIN]
    		,FIFO_full						//	[WRITE DOMAIN]
    		
    );	
    
    
    // PARAMETER DECLARATION
    parameter	FIFO_DATA_WIDTH	=	8;
    parameter	FIFO_ADDR_WIDTH	=	3;
    
    
    // FIFO MEMORY DECLARATION 
    reg			[FIFO_DATA_WIDTH-1 : 0] 	FIFO_MEM		[{(FIFO_ADDR_WIDTH){1'b1}} : 0];
    integer 		i;
    
    
    // INPUT AND OUTPUT DECLARATION
    input 												rst_n;				// SYSTEM RESET (RESET:0)
    input													FIFO_read_clk;		//	READ CLOCK OF READ DOMAIN 
    input													FIFO_write_clk;	// WRITE CLOCK OF WRITE DOMAIN
    input													FIFO_read_en;		// READ ENABLE FROM READ DOMAIN (ENABLE: 1)
    input													FIFO_write_en;		// WRITE ENABLE FROM WRITE DOMAIN (ENABLE: 1)
    input				[FIFO_DATA_WIDTH-1 : 0]		FIFO_write_data;	// DATA WRITE TO FIFO
    
    output												FIFO_read_err;		// ERROR OCCURED WHEN READ IS ENABLED BUT FIFO IS EMPTY (ERR:1)
    output	reg	[FIFO_DATA_WIDTH-1 : 0]		FIFO_read_data;	// DATA READ FROM FIFO
    output												FIFO_write_err;	// ERROR OCCURED WHEN WRITE IS ENABLED BUT FIFO IS FULL (ERR: 1)
    output												FIFO_empty;			// FIFO EMPTY (EMPTY :1)
    output												FIFO_full;			// FIFO FULL (FULL :1)
    
    
    // READ ADDRESS AND WRITE ADDRESS DECLARATION
    reg				[FIFO_ADDR_WIDTH : 0]		FIFO_read_addr;	//	[READ DOMAIN] READ ADDRESS WHEN EXTRA BIT IS USED TO DETECT EMPTY OR FULL
    reg				[FIFO_ADDR_WIDTH : 0]		FIFO_write_addr;	//	[WRITE DOMAIN] WRITE ADDRESS WHEN EXTRA BIT IS USED TO DETECT EMPTY OR FULL
    
    
    //	REG DECLARATION WHICH WILL BE USED WHEN TWO-LEVEL SYNCHRONIZATION
    reg									read_rst_n_1;			// THE FIRST REG OUT WHEN SYNCHRONIZE RST_N TO READ DOMAIN
    reg									read_rst_n_2;			// THE SECOND REG OUT WHEN SYNCHRONIZE RST_N TO READ DOMAIN
    reg									write_rst_n_1;			// THE FIRST REG OUT WHEN SYNCHRONIZE RST_N TO WRITE DOMAIN
    reg									write_rst_n_2;			// THE SECONDE REG OUT WHEN SYNCHRONIZE RST_N TO WRITE DOMAIN
    
    wire				[FIFO_ADDR_WIDTH : 0]		FIFO_read_addr_grey_code;		// TRANSFER THE READ ADDRESS FROM 8421 TO GREY CODE
    wire				[FIFO_ADDR_WIDTH : 0]		FIFO_write_addr_grey_code;		// TRANSFER THE WRITE ADDRESS FROM 8421 TO GREY CODE
    
    reg				[FIFO_ADDR_WIDTH : 0]		FIFO_read_addr_to_write_1;		// THE FIRST REG OUT WHEN SYNCHRONIZE FIFO_read_addr TO WRITE DOMAIN
    reg				[FIFO_ADDR_WIDTH : 0]		FIFO_read_addr_to_write_2;	// THE SECOND REG OUT WHEN SYNCHRONIZE FIFO_read_addr TO WRITE DOMAIN
    reg				[FIFO_ADDR_WIDTH : 0]		FIFO_write_addr_to_read_1;		// THE FIRST REG OUT WHEN SYNCHRONIZE FIFO_write_addr TO READ DOMAIN
    reg				[FIFO_ADDR_WIDTH : 0]		FIFO_write_addr_to_read_2;		// THE SECOND REG OUT WHEN SYNCHRONIZE FIFO_write_addr TO READ DOMAIN
    
    
    
    //--========================== MODULE SOURCE CODE ==========================--
    
    //Synchronize the rst_n to read clock domain and write clock domain
    always @ (posedge FIFO_read_clk or negedge rst_n)
    begin
    	if (!rst_n)
    		begin
    			read_rst_n_1 <= 1'b0;
    			read_rst_n_2 <= 1'b0;
    		end
    	else
    		begin
    			read_rst_n_1 <= 1'b1;
    			read_rst_n_2 <= read_rst_n_1;
    		end
    end
    always @ (posedge FIFO_write_clk or negedge rst_n)
    begin
    	if (!rst_n)
    		begin
    			write_rst_n_1 <= 1'b0;
    			write_rst_n_2 <= 1'b0;
    		end
    	else
    		begin
    			write_rst_n_1 <= 1'b1;
    			write_rst_n_2 <= write_rst_n_1;
    		end
    end
    
    // READ DATA FROM FIFO MEMORY OR WRITE DATA TO FIFO MEMORY
    always @ (posedge FIFO_read_clk)
    begin
    	if (!read_rst_n_2)
    		FIFO_read_data <= {(FIFO_DATA_WIDTH){1'b0}};
    	else if (FIFO_read_en && (!FIFO_empty))
    		FIFO_read_data <= FIFO_MEM[FIFO_read_addr];
    	else 
    		FIFO_read_data <= FIFO_read_data;
    end
    always @ (posedge FIFO_write_clk)
    begin
    	if (!write_rst_n_2)
    		for (i=0;i<=({(FIFO_ADDR_WIDTH){1'b1}});i=i+1)
    			FIFO_MEM[i] <= {(FIFO_DATA_WIDTH){1'b0}};
    	else if (FIFO_write_en && (!FIFO_full))
    		FIFO_MEM[FIFO_write_addr] <= FIFO_write_data;
    	else
    		FIFO_MEM[FIFO_write_addr] <= FIFO_MEM[FIFO_write_addr];
    end
    
    // FIFO READ ADDR INCREASE WHEN DATA IS READ OUT FROM FIFO IN READ DOMAIN
    // FIFO WRITE ADDR INCREASE WHEN DATA IS WRITE INTO FIFO IN WRITE DOMAIN
    always @ (posedge FIFO_read_clk)
    begin
    	if (!read_rst_n_2)	
    		FIFO_read_addr <= {(FIFO_ADDR_WIDTH+1){1'b0}};
    	else if (FIFO_read_en && (!FIFO_empty))
    		FIFO_read_addr <= FIFO_read_addr + 1;
    	else
    		FIFO_read_addr <= FIFO_read_addr;
    end
    always @ (posedge FIFO_write_clk)
    begin
    	if (!write_rst_n_2)
    		FIFO_write_addr <= {(FIFO_ADDR_WIDTH+1){1'b0}};
    	else if (FIFO_write_en && (!FIFO_full))
    		FIFO_write_addr <= FIFO_write_addr + 1;
    	else 
    		FIFO_write_addr <= FIFO_write_addr;
    end
    
    // TRANSFER FIFO_write_addr FROM 8421 BIN CODE TO GREY CODE
    // TRANSDER FIFO_read_addr FROM 8421 BIN CODE TO GREY CODE
    // THE WAYS IS TO MOVE 8421 CODE TO RIGHT SIDE OF ONE BIT, AND MSB WILL BE FILL BY 0;
    // THEN (^) WILL BE USED BETWEEN FORMER AND LATER TO GET GREY CODE 
    assign 	FIFO_read_addr_grey_code 	= ((FIFO_read_addr >> 1) ^ FIFO_read_addr); 
    assign 	FIFO_write_addr_grey_code 	= ((FIFO_write_addr >> 1) ^ FIFO_write_addr); 
    
    // TRANSFER FIFO_write_addr_grey_code TO READ CLOCK DOMAIN THROUGH TWO LEVEL REG
    // TRANSFER FIFO_read_addr_grey_code TO WRITE CLOCK DOMAIN THROUGH TWO LEVEL REG
    always @ (posedge FIFO_read_clk)
    begin
    	if (!read_rst_n_2)
    		begin
    			FIFO_write_addr_to_read_1 <= {(FIFO_ADDR_WIDTH+1){1'b0}};
    			FIFO_write_addr_to_read_2 <= {(FIFO_ADDR_WIDTH+1){1'b0}};
    		end
    	else 
    		begin
    			FIFO_write_addr_to_read_1 <= FIFO_write_addr_grey_code;
    			FIFO_write_addr_to_read_2 <= FIFO_write_addr_to_read_1;
    		end
    end
    always @ (posedge FIFO_write_clk)
    begin
    	if (!write_rst_n_2)
    		begin
    			FIFO_read_addr_to_write_1 <= {(FIFO_ADDR_WIDTH+1){1'b0}};
    			FIFO_read_addr_to_write_2 <= {(FIFO_ADDR_WIDTH+1){1'b0}};
    		end
    	else 
    		begin
    			FIFO_read_addr_to_write_1 <= FIFO_read_addr_grey_code;
    			FIFO_read_addr_to_write_2 <= FIFO_read_addr_to_write_1;
    		end
    end
    
    // ACCORDING TO THE READ ADDRESS GREY CODE AND WRITE ADDRESS GREY CODE IN READ CLOCK DOMAIN TO DETERMIN FIFO ENPTY
    // ACCORDING TO THE READ ADDRESS GREY CODE AND WRITE ADDRESS GREY CODE IN WRITE CLOCK DOMAIN TO DETERMIN FIFO FULL
    // FIFO EMPTY WHEN READ ADDRESS GREY CODE IS THE SAME AS WRITE ADDRESS GREY CODE
    // FIFO FULL WHEN THE MOST SIGNIFICENT TWO CODE OF WRITE AND READ ADDRESS GREY CODE ARE BOTH DIFFERENT AND THE OTHERS ARE THE SAME 
    assign	FIFO_empty 	=	 	(FIFO_read_addr_grey_code == FIFO_write_addr_to_read_2);
    assign 	FIFO_full 	=	 	((!(FIFO_write_addr_grey_code[FIFO_ADDR_WIDTH] 
    								==     FIFO_read_addr_to_write_2[FIFO_ADDR_WIDTH])) 
    							&&		 (!(FIFO_write_addr_grey_code[FIFO_ADDR_WIDTH-1] 
    								==     FIFO_read_addr_to_write_2[FIFO_ADDR_WIDTH-1])) 
    							&& 	(   FIFO_write_addr_grey_code[FIFO_ADDR_WIDTH -2:0] 
    								==     FIFO_read_addr_to_write_2[FIFO_ADDR_WIDTH -2:0]));
    							
    assign  	FIFO_read_err = 		FIFO_empty && FIFO_read_en;
    assign 	FIFO_write_err = 		FIFO_full && FIFO_write_en;
    endmodule
    
    
    

    4.4 、优缺点分析

    优点:读写可以处于不同的时钟域,从而分割模块设计,之后通过FIFO连接起来就行

    缺点:由于采用了两级寄存器来在不同时钟域之间做同步化处理,实际上地址信号的传递慢了两个时钟周期,对于低速信号尚可以接受,但是高速信号就不太好了。


    总结

    本文从单端口RAM、双端口RAM、同步FIFO、异步FIFO出发,分析各个模块的应用场景、代码实现及优缺点分析。

    展开全文
  • Verilog实现RAM(6-双端口异步读写SRAM)

    千次阅读 2020-02-25 14:04:43
    在之前的工作中,我们对常见存储器件进行了名词扫盲,通过调用IP核实现了简单的单端口同步读写SRAM、对单端口同步读写SRAM进行...Verilog实现RAM(5-双端口同步读写SRAM) 现在在之前工作的基础上,进一步实现双端口...
  • Verilog实现RAM(5-双端口同步读写SRAM)

    千次阅读 2020-02-24 20:12:01
    在之前的工作中,我们对常见存储器件进行了名词扫盲,并通过调用IP核实现了简单的单端口同步读写SRAM、对单端口...Verilog实现RAM(2-单端口同步读写SRAM) Verilog实现RAM(3-单端口同步写、异步读SRAM) Verilog实现...
  • verilog实现一个异步双端口ram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合 设计思路 因为要设计双端ram,所以是读写分离,时钟分离,控制信号分离。先确定端口: 端口名 备注 ...
  • 数字IC设计——SRAM的Verilog语言实现(三)(双端口SRAM) 在FPGA设计中,经常会用到RAM,这里的RAM一般指的是静态的RAM(SRAM)。一般FPGA中就有所谓的block RAM, 它就是现成的RAM资源。通常情况下,我们使用IP核...
  • 基于Xilinx spartan6 lx9的片内block ram读写测试; 包含ip核的例化,读写测试数据的写入读出 真口模式,读写设置为no change; 对不同地址边读边写;
  • 【xilink nexsy3】【verilog】存储器RAM

    千次阅读 2018-07-07 15:09:45
    一、实验目的 ...a)例化一个简单双端口RAM(32bitx64) b)使用coe文件对RAM进行初始化 二、实验要求 1.综合利用三次实验的结果,完成以下功能: a)从ram中0地址和1地址读取两个数, 分别赋给reg0...
  • 数字IC设计——SRAM的Verilog语言实现(三)(双端口SRAM) 在FPGA设计中,经常会用到RAM。 1)用Verilog实现一个同步双端口sram,深度16,位宽8bit。A口读出,B口写入。支持片选,读写请求,要求代码可综合。 2)用...
  • 然后,从应用的角度简单介绍了IsSI公司的静态RAM芯片IS61LV256,并阐明了将其作为逻辑分析卡外部RAM的使用方法,设计了该RAM与CPLD的硬件接口。应用Ve rjlog—HDL语言对双向(inout)端口所进行了描述,在此基础上以...
  • ram读写

    千次阅读 2020-06-27 10:36:11
    单端口时读和写不能同时进行,双端口ram多了一个读地址,可以同时读写 设计架构 代码设计 verilog代码设计 ram ipcore创建,位宽10,深度1024 顶层模块设计 module dram_top( input a_clk, input ...
  • (读写数据也可共用一个clk,为同步伪双端口ram) 3 真双端口:一组端口可读可写,另一组端口也可读可写。(若这两组端口共用一个clk,为同步真双端口ram。若每组有每组的clk,为异步真双端口ram) (1)单端口...
  • 7 实现深度16、位宽8bit的伪口异步RAM,a端口读数据,b端口写数据 Verilog代码: module dpram16x8( input clka, input clkb, input rst, input cs, // port a input ren, input [3:0] addra, ...
  • 这个同步FIFO的设计方法是调用异步读写双端口RAM来实现的。 关于异步读写双端口RAM的设计,前面博文已经讲到过了:【FPGA】双端口RAM的设计(异步读写) 此时使用双端口RAM来设计FIFO,可以使用一套端口进行写操作...
  • 基于FPGA的SATA主机控制器接口特性如下: 支持1.5Gbps, 3Gbps,6Gbps线速率 提供fifo数据流接口,支持扁平式地址访问(只需提供首扇区地址和总扇区长度...提供双端口RAM接口,支持1~16个扇区地址访问,实现最多8192-...
  • Verilog8-常用电路(2)

    2020-10-10 20:44:59
    文章目录1、用Verilog实现 串并转换lsb 优先msb 优先2、序列检测器:有“101”序列输入时输出为1,其他情况下输出为03、Verilog实现一个异步双端口 RAM,4、Verilog实现分频器 —— 见专题5、Verilog 实现 glitch ...
  • DUAL PORT RAM应用实例

    2018-05-14 14:00:00
    作者:桂。 时间:2018-05-1412:11:00 ...主要是Xilinx 常用模块汇总(verilog)【03】中双端口RAM的细节补充,限于篇幅,单独列出。 一、双端口RAM简述 具体细节参考ug473_7Series_Memory_Resources.p...
  • FIFO verilog

    2017-03-15 09:40:36
    并且需要在这几个时钟域之间传输数据的时候,寄存器会由于时钟信号的频率不匹配而产生数据丢失等情况,这个时候需要用异步FIFO来进行缓存,保证数据能够正确传输,因此一般异步FIFO会包含一个双端口RAM,...
  • Dual_port_Ram-源码

    2021-03-26 12:39:38
    我尝试使用基于系统Verilog的UVM通过约束随机验证来验证双端口ram,在此我还检查了设计的功能正确性并提取了覆盖率指标。 我尝试寻找的一些功能如下: 在不同的受约束地址中执行读写操作,并检查是否相同。 检查...
  • 存储器。 1. rom,ram,flash,ddr,sram,dram,mram..列举并解释一下这些名词。 2. 用verilog实现一个深度为16,位宽8bit的单端口SRAM。...4. 使用单端口SRAM构造一个双端口同步FIFO。 解答: 1. ro...
  • 目的在于,完全掌握RAM的使用,实现基本的双端口读写。具体有以下几个部分。 1,实现双口RAM,完全掌握调用IP核的流程; 2,要深入了解RAM,那么进行测试,模拟1450字节数据,然后写入RAM看看分布情况; 3,然后在看...
  • 按照配置,内核支持单(1)周期操作,内部Block RAM用作程序存储器。 支持三个I / O端口,但可以使用双向数据总线将它们作为外部寄存器和缓冲区进行访问。 同样支持TRIS I / O控制寄存器。 因此,内核的用户能够以...
  • 应用这三种方案,用硬件描述语言Verilog设计了三种抗故障攻击双端口RAM存储器,在Altera 公司的器件EP1C12Q240C8上予以实现。通过仿真验证,三种带故障检测的RAM具有较高的故障检测概率,而对硬件芯片性能影响不大。
  • 该结构将数据的奇偶分裂、边界延拓嵌入到地址产生单元对双端口RAM的操作中,不需要额外的计算单元,采用移位-相加操作代替卷积操作,通过Verilog编写RTL级代码并进行功能仿真,最后完成了在FPGA上的验证,最高时钟...
  • 该结构将数据的奇偶分裂、边界延拓嵌入到地址产生单元对双端口RAM的操作中,不需要额外的计算单元,采用移位-相加操作代替卷积操作,通过Verilog编写RTL级代码并进行功能仿真,最后完成了在FPGA上的验证,最高时钟...
  • MUSBMHDRC有一个RAM接口,用于连接到用于所有端点FIFOs的同步单端口RAM的单个块。(RAM块本身需要由用户添加。) 端点0的FIFO需要为64字节深,并缓冲1个数据包。RAM接口可以根据其他端点FIFOs进行配置,它的大小可以从...

空空如也

空空如也

1 2
收藏数 32
精华内容 12
关键字:

verilog双端口ram