构建可变变量的存储方式

简介

  在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
相关推荐
仲南音2 天前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner2 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20202 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy3 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia3 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20203 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子3 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
9527华安4 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi
千寻xun4 天前
二、实战篇-NVME SSD控制之ZYNQ实现(六)-读写NVME SSD硬盘数据
fpga开发·nvme·nvme ssd
千寻xun4 天前
二、实战篇-NVME SSD控制之ZYNQ实现(三)
fpga开发·nvme ssd·nvme协议