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

📄 fifo_generator_v2_0.v

📁 Reed-Solomon 信道编码广泛应用于DVB中
💻 V
📖 第 1 页 / 共 5 页
字号:
 input [C_WR_PNTR_WIDTH-1:0]      PROG_FULL_THRESH_NEGATE; input 			          RD_CLK; input 			          RD_EN; input 			          RST; input 			          WR_CLK; input 			          WR_EN; output 		          ALMOST_EMPTY; output 		          ALMOST_FULL; output [C_DOUT_WIDTH-1:0] 	  DOUT; output 			  EMPTY; output 			  FULL; output 			  OVERFLOW; output 			  PROG_EMPTY; output 			  PROG_FULL; output 			  VALID; output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT; output 			  UNDERFLOW; output 			  WR_ACK; output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT; /******************************************************************************* * Input and output register declarations ******************************************************************************//******************************************************************************* * Parameters used as constants ******************************************************************************/   parameter 			  C_FULL_RESET_VAL = 1;   parameter 			  C_ALMOST_FULL_RESET_VAL = 1;   parameter 			  C_PROG_FULL_RESET_VAL = 1;   parameter 			  C_HAS_FAST_FIFO = 0;   parameter 			  C_RATIO_W =  (C_WR_DEPTH>C_RD_DEPTH) ? (C_WR_DEPTH/C_RD_DEPTH) : 1;   parameter 			  C_RATIO_R =  (C_RD_DEPTH>C_WR_DEPTH) ? (C_RD_DEPTH/C_WR_DEPTH) : 1;   parameter 			  C_FIFO_WR_DEPTH = (C_HAS_FAST_FIFO || (C_PRELOAD_REGS && C_PRELOAD_LATENCY) || C_COMMON_CLOCK) ? C_WR_DEPTH : C_WR_DEPTH - 1;   parameter 			  C_FIFO_RD_DEPTH = (C_HAS_FAST_FIFO || (C_PRELOAD_REGS && C_PRELOAD_LATENCY) || C_COMMON_CLOCK) ? C_RD_DEPTH : C_RD_DEPTH - 1;      parameter 			  C_PROG_FULL_REG = 1;   parameter 			  C_PROG_EMPTY_REG = 1;        //Memory which will be used to simulate a FIFO   reg [C_DIN_WIDTH-1:0] 	  memory[C_WR_DEPTH-1:0];   reg [31:0] 			  num_wr_bits;   reg [31:0] 			  num_rd_bits;   reg [31:0] 			  next_num_wr_bits;   reg [31:0] 			  next_num_rd_bits;   reg [31:0] 			  wr_ptr;   reg [31:0] 			  rd_ptr;   reg [31:0] 			  wr_ptr_rdclk;   reg [31:0] 			  wr_ptr_rdclk_q;   reg [31:0] 			  wr_ptr_rdclk_next;   reg [31:0] 			  rd_ptr_wrclk;   reg [31:0] 			  rd_ptr_wrclk_q;   reg [31:0] 			  rd_ptr_wrclk_next;   wire [31:0]                    num_read_words  = num_rd_bits/C_DOUT_WIDTH;   wire [31:0]                    num_write_words = num_wr_bits/C_DIN_WIDTH;   wire [31:0]                    reads_per_write = C_DIN_WIDTH/C_DOUT_WIDTH;   wire [31:0]                    log2_reads_per_write = log2_val(reads_per_write);   wire [31:0] 			  writes_per_read = C_DOUT_WIDTH/C_DIN_WIDTH;   wire [31:0]                    log2_writes_per_read = log2_val(writes_per_read);      /*******************************************************************************    * Internal Registers and wires    ******************************************************************************/   wire 			  wr_ack_i;   wire 			  overflow_i;   wire 			  underflow_i;   wire 			  valid_i;         //Special ideal FIFO signals   reg [C_DOUT_WIDTH-1:0] 	  ideal_dout;   reg 				  ideal_wr_ack;   reg 				  ideal_valid;   reg 				  ideal_overflow;   reg 				  ideal_underflow;   reg 				  ideal_full;   reg 				  ideal_empty;   reg 				  ideal_almost_full;   reg 				  ideal_almost_empty;   reg 				  ideal_prog_full;   reg 				  ideal_prog_empty;      //MSBs of the counts   reg [C_WR_DATA_COUNT_WIDTH-1 : 0] ideal_wr_count;   reg [C_WR_DATA_COUNT_WIDTH-1 : 0] ideal_wr_count_q;    reg [C_RD_DATA_COUNT_WIDTH-1 : 0] ideal_rd_count;   reg [C_RD_DATA_COUNT_WIDTH-1 : 0] ideal_rd_count_q;       //user specified value for reseting the size of the fifo   reg [C_DOUT_WIDTH-1:0] 	     dout_reset_val;   //temporary registers for WR_RESPONSE_LATENCY feature   reg 				     ideal_wr_ack_q;   reg 				     ideal_overflow_q;      integer                           tmp_wr_listsize;   integer                           tmp_rd_listsize;   //Signal for registered version of prog full and empty   reg 				     prog_full_d;   reg 				     prog_empty_d;      /****************************************************************************    * Function Declarations    ***************************************************************************/      task write_fifo;      begin	 memory[wr_ptr]     <= DIN;	 if (wr_ptr == 0) begin	    wr_ptr          <= C_WR_DEPTH - 1;	 end else begin	    wr_ptr          <= wr_ptr - 1;	 end	      end   endtask // write_fifo      task  read_fifo;	integer i;	reg [C_DOUT_WIDTH-1:0] tmp_dout;	reg [C_DIN_WIDTH-1:0]  memory_read;	reg [31:0]             tmp_rd_ptr;	reg [31:0]             rd_ptr_high;	reg [31:0]             rd_ptr_low;      begin	 // output is wider than input	 if (reads_per_write == 0) begin	    tmp_dout = 0;	    tmp_rd_ptr = (rd_ptr << log2_writes_per_read)+(writes_per_read-1);	    for (i = writes_per_read - 1; i >= 0; i = i - 1) begin	       tmp_dout = tmp_dout << C_DIN_WIDTH;	       tmp_dout = tmp_dout | memory[tmp_rd_ptr];	       if (tmp_rd_ptr == 0) begin		  tmp_rd_ptr = C_WR_DEPTH - 1;	       end else begin		  tmp_rd_ptr = tmp_rd_ptr - 1;	       end	    end	    	 // output is symmetric	 end else if (reads_per_write == 1) begin	    tmp_dout = memory[rd_ptr];	    	 // input is wider than output	 end else begin	    rd_ptr_high = rd_ptr >> log2_reads_per_write;	    rd_ptr_low  = rd_ptr & (reads_per_write - 1);	    memory_read = memory[rd_ptr_high];	    tmp_dout = memory_read >> (rd_ptr_low*C_DOUT_WIDTH);	 end	 ideal_dout <= tmp_dout;	 if (rd_ptr == 0) begin	    rd_ptr <= C_RD_DEPTH - 1;	 end else begin	    rd_ptr <= rd_ptr - 1;	 end      end      endtask      /****************************************************************************    * log2_va    *   Returns the 'log2' value for the input value for the supported ratios    ***************************************************************************/    function [31:0] log2_val;    input [31:0] binary_val;          begin       if (binary_val == 8) begin	  log2_val = 3;       end else if (binary_val == 4) begin	  log2_val = 2;       end else begin	  log2_val = 1;       end    end    endfunction   /*************************************************************************    * hexstr_conv    *   Converts a string of type hex to a binary value (for C_DOUT_RST_VAL)    ***********************************************************************/     function [C_DOUT_WIDTH-1:0] hexstr_conv;    input [(C_DOUT_WIDTH*8)-1:0] def_data;     integer index,i,j;    reg [3:0] bin;     begin      index = 0;      hexstr_conv = 'b0;      for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 )      begin	case (def_data[7:0])	  8'b00000000 :	  begin	    bin = 4'b0000;	    i = -1;	  end	  8'b00110000 : bin = 4'b0000;	  8'b00110001 : bin = 4'b0001;	  8'b00110010 : bin = 4'b0010;	  8'b00110011 : bin = 4'b0011;	  8'b00110100 : bin = 4'b0100;	  8'b00110101 : bin = 4'b0101;	  8'b00110110 : bin = 4'b0110;	  8'b00110111 : bin = 4'b0111;	  8'b00111000 : bin = 4'b1000;	  8'b00111001 : bin = 4'b1001;	  8'b01000001 : bin = 4'b1010;	  8'b01000010 : bin = 4'b1011;	  8'b01000011 : bin = 4'b1100;	  8'b01000100 : bin = 4'b1101;	  8'b01000101 : bin = 4'b1110;	  8'b01000110 : bin = 4'b1111;	  8'b01100001 : bin = 4'b1010;	  8'b01100010 : bin = 4'b1011;	  8'b01100011 : bin = 4'b1100;	  8'b01100100 : bin = 4'b1101;	  8'b01100101 : bin = 4'b1110;	  8'b01100110 : bin = 4'b1111;	  default :	  begin	    bin = 4'bx;	  end	endcase	for( j=0; j<4; j=j+1)	begin	  if ((index*4)+j < C_DOUT_WIDTH)	  begin	    hexstr_conv[(index*4)+j] = bin[j];	  end	end	index = index + 1;	def_data = def_data >> 8;      end    end  endfunction     /*************************************************************************    * Initialize Signals    *************************************************************************/   initial     begin	num_wr_bits        = 0;	num_rd_bits        = 0;	next_num_wr_bits   = 0;	next_num_rd_bits   = 0;	rd_ptr              = C_RD_DEPTH - 1;	wr_ptr              = C_WR_DEPTH - 1;	rd_ptr_wrclk        = rd_ptr;	rd_ptr_wrclk_q      = rd_ptr;	wr_ptr_rdclk        = wr_ptr;	wr_ptr_rdclk_q      = wr_ptr;	dout_reset_val      = hexstr_conv(C_DOUT_RST_VAL);	ideal_dout          = dout_reset_val;	ideal_wr_ack        = 1'b0;	ideal_valid         = 1'b0;	ideal_overflow      = 1'b0;	ideal_underflow     = 1'b0;	ideal_full          = 1'b1;	ideal_empty         = 1'b1;	ideal_almost_full   = 1'b1;	ideal_almost_empty  = 1'b1;	ideal_wr_count      = 0;	ideal_rd_count      = 0;	ideal_prog_full     = 1'b1;	ideal_prog_empty    = 1'b1;	prog_full_d         = 1'b1;	prog_empty_d        = 1'b1;     end         /*************************************************************************    * Assign Internal ideal signals to output ports    *************************************************************************/   assign DOUT         = ideal_dout;   assign FULL         = ideal_full;   assign EMPTY        = ideal_empty;   assign ALMOST_FULL  = ideal_almost_full;   assign ALMOST_EMPTY = ideal_almost_empty;   assign WR_DATA_COUNT= ideal_wr_count;   assign RD_DATA_COUNT= ideal_rd_count_q;   assign PROG_FULL    = (C_PROG_FULL_REG==1) ? ideal_prog_full : prog_full_d;   assign PROG_EMPTY   = (C_PROG_EMPTY_REG==1) ? ideal_prog_empty : prog_empty_d;       //Handshaking signals can be active low, depending on _LOW parameters   assign valid_i      = (C_PRELOAD_LATENCY==0) ? (RD_EN & ~EMPTY) : ideal_valid;   assign VALID        = valid_i ? !C_VALID_LOW : C_VALID_LOW;   assign underflow_i  = (C_PRELOAD_LATENCY==0) ? (RD_EN & EMPTY) : ideal_underflow;   assign UNDERFLOW    = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW;      assign WR_ACK       = wr_ack_i ? !C_WR_ACK_LOW : C_WR_ACK_LOW;   assign wr_ack_i     = (C_WR_RESPONSE_LATENCY==2) ? ideal_wr_ack_q : 			 (C_WR_RESPONSE_LATENCY==1) ? ideal_wr_ack :			    (WR_EN & !FULL);   assign OVERFLOW     = overflow_i ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW;   assign overflow_i   = (C_WR_RESPONSE_LATENCY==2) ? ideal_overflow_q : 			 (C_WR_RESPONSE_LATENCY==1) ? ideal_overflow :			    (WR_EN & FULL);         always @(posedge WR_CLK or posedge RST ) begin : gen_fifo_w      /****** Reset fifo (case 1)***************************************/      if (RST == 1'b1) begin	 num_wr_bits       <= 0;	 next_num_wr_bits  <= 0;	 wr_ptr            <= C_WR_DEPTH - 1;	 rd_ptr_wrclk      <= C_RD_DEPTH - 1;	 rd_ptr_wrclk_q    <= C_RD_DEPTH - 1;	 ideal_wr_ack      <= 0; 	 ideal_overflow    <= 0;	 ideal_full        <= C_FULL_RESET_VAL; //1'b1;	 ideal_almost_full <= C_ALMOST_FULL_RESET_VAL; //1'b1;	 ideal_wr_count    <= 0;	 ideal_wr_count_q  <= 0;	 ideal_prog_full   <= C_PROG_FULL_RESET_VAL; //1'b1;	       end else begin	 	 //Determine the current number of words in the FIFO  	 tmp_wr_listsize = (C_RATIO_R > 1) ? num_wr_bits/C_DOUT_WIDTH :			   num_wr_bits/C_DIN_WIDTH;	 rd_ptr_wrclk_next = rd_ptr;	 if (rd_ptr_wrclk < rd_ptr_wrclk_next) begin	    next_num_wr_bits = num_wr_bits - 			       C_DOUT_WIDTH*(rd_ptr_wrclk + C_RD_DEPTH					     - rd_ptr_wrclk_next);	 end else begin	    next_num_wr_bits = num_wr_bits - 			       C_DOUT_WIDTH*(rd_ptr_wrclk - rd_ptr_wrclk_next);	 end	 	 //If this is a write, handle the write by adding the value	 // to the linked list, and updating all outputs appropriately	 if (WR_EN == 1'b1) begin	    if (ideal_full == 1'b1) begin	       	       //If the FIFO is full, do NOT perform the write, 	       // update flags accordingly	       if ((tmp_wr_listsize + C_RATIO_R - 1)/C_RATIO_R >= C_FIFO_WR_DEPTH)		 begin		    //write unsuccessful - do not change contents		    		    //Do not acknowledge the write		    ideal_wr_ack <= 0;		    //throw an overflow error		    ideal_overflow <= 1;		    //Reminder that FIFO is still full		    ideal_full   <= 1'b1;		    ideal_almost_full   <= 1'b1;		    		    ideal_wr_count <= num_write_words[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH];		    		    //If the FIFO is one from full, but reporting full		 end else if ((tmp_wr_listsize + C_RATIO_R - 1)/C_RATIO_R == 			      C_FIFO_WR_DEPTH-1) begin		    //No change to FIFO		    //Write not successful		    ideal_wr_ack <= 0;		    ideal_overflow <= 1;		    //With DEPTH-1 words in the FIFO, it is almost_full		    ideal_full   <= 1'b0; 		    ideal_almost_full  <= 1'b1;		    		    ideal_wr_count     <= num_write_words[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH];		    		    		    //If the FIFO is completely empty, but it is		    // reporting FULL for some reason (like reset)		 end else if ((tmp_wr_listsize + C_RATIO_R - 1)/C_RATIO_R <= 			      C_FIFO_WR_DEPTH-2) begin		    //No change to FIFO

⌨️ 快捷键说明

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