构建可变变量的存储方式

构建可变变量的存储方式

码农世界 2024-06-04 前端 83 次浏览 0个评论

简介

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

FIFO

`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 

RAM

带有两个写端口的双端RAM

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

//带有两个写端口的双端块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

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

// 写优先模式的单端块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时钟读

//双时钟控制,伪双端块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

转载请注明来自码农世界,本文标题:《构建可变变量的存储方式》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,83人围观)参与讨论

还没有评论,来说两句吧...

Top