⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syncore_ram.v

📁 任意时钟配比的异步fifo.含有synplify ip库中的双端口ram。用于处理多时钟域问题。
💻 V
字号:

/**********************************************************************************

 This Module infers Generic Dual Port RAMs in Xilinx or Altera or Actel

	 All RESETs are made Synchronous

********************************************************************************/


`define SYN_MULTI_PORT_RAM 1 

`ifdef SYN_MULTI_PORT_RAM 
   `define RAM_STYLE /* synthesis syn_ramstyle = "no_rw_check" */ 
 `else
   `define RAM_STYLE /* synthesis syn_ramstyle = "block_ram" */ 
 `endif
    


module Syncore_ram(
	 PortClk
	,PortReset
	,PortWriteEnable
	,PortReadEnable 
	,PortDataIn
	,PortAddr
	,PortDataOut   
	);


parameter	 DATAWIDTH = 8;
parameter	 ADDRWIDTH = 8; 
parameter	 MEMDEPTH = 2**(ADDRWIDTH);

parameter 	 SPRAM	= 1;
parameter 	 READ_MODE_A			= 1;
parameter	 READ_WRITE_A			= 1;
parameter	 ENABLE_WR_PORTA	 	= 1; 

parameter	 REGISTER_RD_ADDR_PORTA 	= 1; 

parameter	 REGISTER_OUTPUT_PORTA 		= 1; 
parameter	 ENABLE_OUTPUT_REG_PORTA 	= 1; 
parameter	 RESET_OUTPUT_REG_PORTA 	= 1; 


parameter 	 READ_MODE_B			= 1;
parameter	 READ_WRITE_B			= 1;
parameter	 ENABLE_WR_PORTB	 	= 1; 

parameter	 REGISTER_RD_ADDR_PORTB 	= 1; 

parameter	 REGISTER_OUTPUT_PORTB 		= 1; 
parameter	 ENABLE_OUTPUT_REG_PORTB 	= 1; 
parameter	 RESET_OUTPUT_REG_PORTB 	= 1; 


parameter 	 TWO				= 2;


input  [TWO -1:0]				PortClk; 
input  [TWO -1:0]				PortReset;
input  [TWO -1:0]				PortWriteEnable;
input  [TWO -1:0]				PortReadEnable;
input  [ADDRWIDTH*TWO-1:0] 		PortAddr;
input  [DATAWIDTH*TWO-1:0] 			PortDataIn; 
output [DATAWIDTH*TWO-1:0]	 		PortDataOut;




reg [DATAWIDTH*TWO-1:0] DataOutRegPort;
reg [ADDRWIDTH*TWO-1:0] AddrRegPort;



reg [DATAWIDTH*TWO-1:0] mem [MEMDEPTH-1:0] `RAM_STYLE;


wire [TWO -1:0] ResetOutputRegPort; 
wire [TWO -1:0] EnableOutputRegPort;


wire [ADDRWIDTH*TWO-1:0] MemAddrPort;


wire [TWO -1:0] 	 		NOCHANGE;
wire [TWO -1:0] 			WriteEnablePort;
wire [DATAWIDTH*TWO-1:0] 		StoreDout;


wire [TWO -1:0]  Prm_NOCHANGE			= {(READ_MODE_B == 3), (READ_MODE_A == 3)};
wire [TWO -1:0]	 Prm_WRITE_FIRST		= {(READ_MODE_B == 2), (READ_MODE_A == 2)};
wire [TWO -1:0]	 Prm_READ_FIRST			= {(READ_MODE_B == 1), (READ_MODE_A == 1)};

wire [TWO -1:0]  Prm_ENABLE_WR_PORT 		= {(ENABLE_WR_PORTB > 0), (ENABLE_WR_PORTA > 0)}; 

wire [TWO -1:0]	 Prm_REGISTER_RD_ADDR_PORT 	= {(REGISTER_RD_ADDR_PORTB > 0), (REGISTER_RD_ADDR_PORTA > 0)}; 
wire [TWO -1:0]	 Prm_REGISTER_OUTPUT_PORT 	= {(REGISTER_OUTPUT_PORTB > 0), (REGISTER_OUTPUT_PORTA > 0)}; 
wire [TWO -1:0]	 Prm_ENABLE_OUTPUT_REG_PORT 	= {(ENABLE_OUTPUT_REG_PORTB > 0), (ENABLE_OUTPUT_REG_PORTA > 0)}; 
wire [TWO -1:0]	 Prm_RESET_OUTPUT_REG_PORT  	= {(RESET_OUTPUT_REG_PORTB > 0), (RESET_OUTPUT_REG_PORTA > 0)}; 


parameter Rd_Iterations	 = 	SPRAM ? 1 : 
				((((READ_WRITE_A == 1) & (READ_WRITE_B == 1)) | 
				((READ_WRITE_A == 1) & (READ_WRITE_B == 2))   |
				((READ_WRITE_A == 2) & (READ_WRITE_B == 1)) ) ? 2 : 1);

parameter Wr_Iterations = 	SPRAM ? 1 : 
				((((READ_WRITE_A == 1) & (READ_WRITE_B == 1)) | 
			   	((READ_WRITE_A == 1) & (READ_WRITE_B == 3))   |
			   	((READ_WRITE_A == 3) & (READ_WRITE_B == 1)) ) ? 2 : 1);

parameter rd_inc 		=  SPRAM ? 0 : 
				  ((((READ_WRITE_A == 3) & (READ_WRITE_B == 1)) | 						
				  ((READ_WRITE_A == 3) & (READ_WRITE_B == 2)) ) ? 1 : 0);

parameter wr_inc 		=  SPRAM ? 0 : 
				   ((((READ_WRITE_A == 2) & (READ_WRITE_B == 1)) | 						
				   ((READ_WRITE_A == 2) & (READ_WRITE_B == 3)) ) ? 1 : 0);




// Start GENERATE Process
// This block reads from the memory.

generate 
begin : GenBlock1

genvar i ;

for (i=0 ; i < Rd_Iterations; i=i+1)
begin : RAM_READ


assign ResetOutputRegPort[(i+rd_inc)]  	=  (Prm_RESET_OUTPUT_REG_PORT[(i+rd_inc)] > 0) ? PortReset[(i+rd_inc)] : 1'b0 ; 
assign EnableOutputRegPort[(i+rd_inc)] 	=  (Prm_ENABLE_OUTPUT_REG_PORT[(i+rd_inc)] > 0) ? PortReadEnable[(i+rd_inc)] : 1'b1;

assign NOCHANGE[(i+rd_inc)]		 		= (Prm_NOCHANGE[(i+rd_inc)]) ? !WriteEnablePort[(i+rd_inc)] : 1'b1;

/*
 Indexed vector part selects
In the Verilog-1995 standard, variable bit selects of a vector are permitted, but part-selects must be constant.
Thus, it is illegal to use a variable to select a specific byte out of a word. The Verilog-2001 standard adds a new
syntax, called indexed part selects. With an indexed part select, a base expression, a width expression, and an offset
direction are provided, in the form of: 

[base_expr +: width_expr] //positive offset
[base_expr -: width_expr] //negative offset

The base expression can vary during simulation run-time.The width expression must be constant. The offset
direction indicates if the width expression is added to or subtracted from the base expression. For example,:

reg [63:0] word;
reg [3:0] byte_num; //a value from 0 to 7
wire [7:0] byteN = word[byte_num*8 +: 8];

In the preceding example, if byte_num has a value of 4,
then the value of word[39:32] is assigned to byteN. Bit 32
of the part select is derived from the base expression, and
bit 39 from the positive offset and width expression.

*/
assign MemAddrPort[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH]	=  (Prm_REGISTER_RD_ADDR_PORT[(i+rd_inc)] > 0) ? AddrRegPort[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH]
												   			: PortAddr[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH];
									   
assign StoreDout[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] 	= (Prm_WRITE_FIRST[(i+rd_inc)]) ? ( WriteEnablePort[(i+rd_inc)] ? PortDataIn[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] : mem[MemAddrPort[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH]])
															  	   :  mem[MemAddrPort[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH]];

assign PortDataOut[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] 	=  (Prm_REGISTER_OUTPUT_PORT[(i+rd_inc)] > 0) ? DataOutRegPort[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] 
															  : StoreDout[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] ;


// Reading from memory through Port A

always @(posedge PortClk[(i+rd_inc)])
begin  
     AddrRegPort[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH] <= PortAddr[(i+rd_inc)*ADDRWIDTH +: ADDRWIDTH];	
end


always @(posedge PortClk[(i+rd_inc)])
begin
  if(ResetOutputRegPort[(i+rd_inc)])
    DataOutRegPort[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] ='d0;
  else
    if (EnableOutputRegPort[(i+rd_inc)])
      if (NOCHANGE[(i+rd_inc)])
        DataOutRegPort[(i+rd_inc)*DATAWIDTH +: DATAWIDTH] = StoreDout[(i+rd_inc)*DATAWIDTH +: DATAWIDTH];	
end

end
end
endgenerate 



generate 
begin : GenBlock2

genvar j ;

for (j=0 ; j < Wr_Iterations; j=j+1)
begin : RAM_WRITE

assign WriteEnablePort[(j+wr_inc)]		=  (Prm_ENABLE_WR_PORT[(j+wr_inc)] > 0) ? PortWriteEnable[(j+wr_inc)] : 1'b1; 

always @(posedge PortClk[(j+wr_inc)])
begin
   if(WriteEnablePort[(j+wr_inc)]) 
     mem[PortAddr[(j+wr_inc)*ADDRWIDTH +: ADDRWIDTH]] <= PortDataIn[(j+wr_inc)*DATAWIDTH +: DATAWIDTH];		
end

end
end
endgenerate 


endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -