构建可变变量的存储方式

简介

在FPGA中最常用的IP核就是FIFO和RAM了,这两个通常由官方IP来实现,但是在IP中,如果想要修改参数就十分困难。因此就需要构建可变存储空间的FIFO和RAM。通常构建FIFO可以用XILINX提供的源语以及宏来实现,构建小容量的RAM可以用LUT来实现。

FIFO

c 复制代码
`timescale 1ns / 1ps

module xpm_asfifo #(
	parameter FIFO_MEMORY_TYPE  	= "block"	, //block distributed  
	parameter WRITE_DATA_WIDTH  	= 32		, 
	parameter FIFO_WRITE_DEPTH  	= 2048		,
	parameter WR_DATA_COUNT_WIDTH   = 12		,
	parameter READ_MODE         	= "std"		,//"std" "fwft" 
	parameter READ_DATA_WIDTH   	= 32		,
	parameter RD_DATA_COUNT_WIDTH   = 12		,
	parameter FIFO_READ_LATENCY 	= 1			 	
)
(
	input								rst       		,   	
	input								wr_clk			,		
    input								rd_clk			,	
    input	[WRITE_DATA_WIDTH-1:0]		din				,			
    input								wr_en			,			
    input								rd_en			,	
    output	[READ_DATA_WIDTH-1:0]		dout			,	
    output								full			,			
    output								empty			,	
    output	[RD_DATA_COUNT_WIDTH-1:0]	rd_data_count	,
    output	[WR_DATA_COUNT_WIDTH-1:0]	wr_data_count	
);

wire	pre_full	;
wire	wr_rst_busy	;

wire [WRITE_DATA_WIDTH-1:0] din_sw	;
wire [READ_DATA_WIDTH-1:0]  dout_sw	;

genvar i;
generate 
	if(WRITE_DATA_WIDTH>=READ_DATA_WIDTH)
		for(i = 0; i < WRITE_DATA_WIDTH/READ_DATA_WIDTH; i = i + 1) 
		begin
			assign din_sw[i*READ_DATA_WIDTH+:READ_DATA_WIDTH] = din[WRITE_DATA_WIDTH - READ_DATA_WIDTH - i*READ_DATA_WIDTH+:READ_DATA_WIDTH];
		end
	else
		assign din_sw = din;
endgenerate

genvar j;
generate 
		if(WRITE_DATA_WIDTH<READ_DATA_WIDTH)
			for(j = 0; j < READ_DATA_WIDTH/WRITE_DATA_WIDTH; j = j + 1) 
			begin
				assign dout[j*WRITE_DATA_WIDTH+:WRITE_DATA_WIDTH] = dout_sw[READ_DATA_WIDTH - WRITE_DATA_WIDTH - j*WRITE_DATA_WIDTH+:WRITE_DATA_WIDTH];
			end
		else
			assign dout = dout_sw;	
endgenerate

assign full = wr_rst_busy|pre_full;


xpm_fifo_async #(
  .CDC_SYNC_STAGES(2),       // DECIMAL
  .DOUT_RESET_VALUE("0"),    // String
  .ECC_MODE("no_ecc"),       // String
  .FIFO_MEMORY_TYPE(FIFO_MEMORY_TYPE), // String
  .FIFO_READ_LATENCY(FIFO_READ_LATENCY),     // DECIMAL
  .FIFO_WRITE_DEPTH(FIFO_WRITE_DEPTH),   // DECIMAL
  .FULL_RESET_VALUE(0),      // DECIMAL
  .PROG_EMPTY_THRESH(10),    // DECIMAL
  .PROG_FULL_THRESH(10),     // DECIMAL
  .RD_DATA_COUNT_WIDTH(RD_DATA_COUNT_WIDTH),   // DECIMAL
  .READ_DATA_WIDTH(READ_DATA_WIDTH),      // DECIMAL
  .READ_MODE(READ_MODE),         // String
  .RELATED_CLOCKS(0),        // DECIMAL
  //.SIM_ASSERT_CHK(0),        // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
  .USE_ADV_FEATURES("0707"), // String
  .WAKEUP_TIME(0),           // DECIMAL
  .WRITE_DATA_WIDTH(WRITE_DATA_WIDTH),     // DECIMAL
  .WR_DATA_COUNT_WIDTH(WR_DATA_COUNT_WIDTH)    // DECIMAL
)
xpm_fifo_async_inst (
  .almost_empty(),   // 1-bit output: Almost Empty : When asserted, this signal indicates that
								 // only one more read can be performed before the FIFO goes to empty.

  .almost_full(),     // 1-bit output: Almost Full: When asserted, this signal indicates that
								 // only one more write can be performed before the FIFO is full.

  .data_valid(),       // 1-bit output: Read Data Valid: When asserted, this signal indicates
								 // that valid data is available on the output bus (dout).

  .dbiterr(),             // 1-bit output: Double Bit Error: Indicates that the ECC decoder detected
								 // a double-bit error and data in the FIFO core is corrupted.

  .dout(dout_sw),                   // READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven
								 // when reading the FIFO.

  .empty(empty),                 // 1-bit output: Empty Flag: When asserted, this signal indicates that the
								 // FIFO is empty. Read requests are ignored when the FIFO is empty,
								 // initiating a read while empty is not destructive to the FIFO.

  .full(pre_full),                   // 1-bit output: Full Flag: When asserted, this signal indicates that the
								 // FIFO is full. Write requests are ignored when the FIFO is full,
								 // initiating a write when the FIFO is full is not destructive to the
								 // contents of the FIFO.

  .overflow(),           // 1-bit output: Overflow: This signal indicates that a write request
								 // (wren) during the prior clock cycle was rejected, because the FIFO is
								 // full. Overflowing the FIFO is not destructive to the contents of the
								 // FIFO.

  .prog_empty(),       // 1-bit output: Programmable Empty: This signal is asserted when the
								 // number of words in the FIFO is less than or equal to the programmable
								 // empty threshold value. It is de-asserted when the number of words in
								 // the FIFO exceeds the programmable empty threshold value.

  .prog_full(),         // 1-bit output: Programmable Full: This signal is asserted when the
								 // number of words in the FIFO is greater than or equal to the
								 // programmable full threshold value. It is de-asserted when the number of
								 // words in the FIFO is less than the programmable full threshold value.

  .rd_data_count(rd_data_count), // RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates the
								 // number of words read from the FIFO.

  .rd_rst_busy(),     // 1-bit output: Read Reset Busy: Active-High indicator that the FIFO read
								 // domain is currently in a reset state.

  .sbiterr(),             // 1-bit output: Single Bit Error: Indicates that the ECC decoder detected
								 // and fixed a single-bit error.

  .underflow(),         // 1-bit output: Underflow: Indicates that the read request (rd_en) during
								 // the previous clock cycle was rejected because the FIFO is empty. Under
								 // flowing the FIFO is not destructive to the FIFO.

  .wr_ack(),               // 1-bit output: Write Acknowledge: This signal indicates that a write
								 // request (wr_en) during the prior clock cycle is succeeded.

  .wr_data_count(wr_data_count), // WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates
								 // the number of words written into the FIFO.

  .wr_rst_busy(wr_rst_busy),     // 1-bit output: Write Reset Busy: Active-High indicator that the FIFO
								 // write domain is currently in a reset state.

  .din(din_sw),                     // WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when
								 // writing the FIFO.

  .injectdbiterr(1'b0), // 1-bit input: Double Bit Error Injection: Injects a double bit error if
								 // the ECC feature is used on block RAMs or UltraRAM macros.

  .injectsbiterr(1'b0), // 1-bit input: Single Bit Error Injection: Injects a single bit error if
								 // the ECC feature is used on block RAMs or UltraRAM macros.

  .rd_clk(rd_clk),               // 1-bit input: Read clock: Used for read operation. rd_clk must be a free
								 // running clock.

  .rd_en(rd_en),                 // 1-bit input: Read Enable: If the FIFO is not empty, asserting this
								 // signal causes data (on dout) to be read from the FIFO. Must be held
								 // active-low when rd_rst_busy is active high.

  .rst(rst),                     // 1-bit input: Reset: Must be l to wr_clk. The clock(s) can be
								 // unstable at the time of applying reset, but reset must be released only
								 // after the clock(s) is/are stable.

  .sleep(1'b0),                 // 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo
								 // block is in power saving mode.

  .wr_clk(wr_clk),               // 1-bit input: Write clock: Used for write operation. wr_clk must be a
								 // free running clock.

  .wr_en(wr_en)                  // 1-bit input: Write Enable: If the FIFO is not full, asserting this
								 // signal causes data (on din) to be written to the FIFO. Must be held
								 // active-low when rst or wr_rst_busy is active high.

);

// End of xpm_fifo_async_inst instantiation
endmodule

RAM

带有两个写端口的双端RAM

首先例化一个大的二维数组。端口A和端口B都可写,但只有端口B可读

c 复制代码
//带有两个写端口的双端块RAM
module tdpram #(
	parameter AW = 10, 	//地址位宽
	parameter DW = 8    //数据位宽
)
(
    input 					clka	, 	
	input 					clkb	,
	input 					wea		,
	input 					web		,
    input 		[AW-1:0] 	addra	,
	input 		[AW-1:0]	addrb	,
    input 		[DW-1:0]	dina	,
	input 		[DW-1:0]	dinb	,
    output reg  [DW-1:0] 	douta	,
	output reg  [DW-1:0] 	doutb
);

reg [DW-1:0] ram [(2**AW)-1:0];    //例化存储空间

//初始化存储空间
integer i;
initial for (i=0; i < (2**AW); i=i+1) ram[i] = 0;

//port 1
always@(posedge clka)      
    if (wea) 
		ram[addra] <= dina;
		
always@(posedge clka)
    douta <= ram[addra];
	
//port 2
always@(posedge clkb)
    if (web) 
		ram[addrb] <= dinb;
		
//端口b可读
always@(posedge clkb)		
	doutb <= ram[addrb];	
		

endmodule

写优先模式的单端块RAM

和上面的例化一样,但是当有写使能的时候,读数据的端口不刷新,即写数据优先

c 复制代码
// 写优先模式的单端块RAM,Wrist_first
module spram #(
	parameter AW = 10,
	parameter DW = 8 
)
(
    input 					clka	, 
	input					wea		, 
    input 		[AW-1:0]	addra	, 
    input 		[DW-1:0]	dina	, 
    output reg 	[DW-1:0]	douta
);

reg [DW-1:0] ram [(2**AW)-1:0];

integer i;
initial for (i=0; i < (2**AW); i=i+1) ram[i] = 0;

always @(posedge clka)
    if (wea)
		begin
			ram[addra] 	<= dina;
			douta 		<= dina;
		end
    else 
		douta <= ram[addra];

endmodule

双时钟控制,伪双端块RAM

A时钟写 B时钟读

c 复制代码
//双时钟控制,伪双端块RAM
module sdpram #(
	parameter AW = 10,
	parameter DW = 8 
)
(
    input 					clka	,
	input 					clkb	,
	input 					wea		,
    input 		[AW-1:0]	addra	,
	input 		[AW-1:0]	addrb	,
    input 		[DW-1:0]	dina	,
    output reg 	[DW-1:0]	doutb
);

reg [DW-1:0] ram [(2**AW)-1:0];

integer i;
initial for (i=0; i < (2**AW); i=i+1) ram[i] = 0;

always@(posedge clka)
    if (wea) 
		ram[addra] <= dina;

always@(posedge clkb)
    doutb <= ram[addrb];

endmodule
相关推荐
北城笑笑7 小时前
FPGA 14 ,硬件开发板分类详解,FPGA开发板与普通开发板烧录的区别
fpga开发·fpga
2202_754421547 小时前
一个计算频率的模块
驱动开发·fpga开发
小灰灰的FPGA9 小时前
低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能
fpga开发
fei_sun1 天前
【Verilog】第一章作业
fpga开发·verilog
深圳市雷龙发展有限公司longsto1 天前
基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面
fpga开发
9527华安1 天前
FPGA实现PCIE3.0视频采集转10G万兆UDP网络输出,基于XDMA+GTH架构,提供工程源码和技术支持
网络·fpga开发·udp·音视频·xdma·pcie3.0·万兆网
able陈1 天前
为什么verilog中递归函数需要定义为automatic?
fpga开发
fei_sun1 天前
【Verilog】第二章作业
fpga开发·verilog
碎碎思1 天前
如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目
fpga开发·接口隔离原则
江山如画,佳人北望2 天前
fpga-状态机的设计及应用
fpga开发