简介
在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_WIDTHRAM
带有两个写端口的双端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
还没有评论,来说两句吧...