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

📄 lp_rx.v

📁 altera fpga 和ts201的linkport接口设计
💻 V
字号:
// ================================================================================
// (c) 2003 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents, maskwork
// rights, copyrights and other intellectual property laws.
// 
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design License
// Agreement (either as signed by you, agreed by you upon download or as a
// "click-through" agreement upon installation andor found at www.altera.com).
// By using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation.  In the event that you do
// not agree with such terms and conditions, you may not use the reference design
// file and please promptly destroy any copies you have made.
// 
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without limitation,
// warranties of merchantability, non-infringement, or fitness for a particular
// purpose, are specifically disclaimed.  By making this reference design file
// available, Altera expressly does not recommend, suggest or require that this
// reference design file be used in combination with any other product not
// provided by Altera.
// ================================================================================

module lp_rx (clk,
	      rst_n,

	      datain,
	      inclock,
	      inclock_en,

	      acko,
	      bcmpi_n,

	      rvere,
	      rcser,

	      rdreq,
	      empty,
	      rdata
	      );

  input clk;		// Local clock
  input rst_n;

  // Link port
  input	[3:0]  datain;
  input        inclock;
  input        inclock_en;

  output       acko;
  input        bcmpi_n;

  // Local control/status
  input        rvere;	// Receive verification byte enable
  output       rcser;	// Receive checksum error
  
  // Local FIFO interface
  input        rdreq;
  output       empty;
  output [32:0] rdata;

  parameter 	DEVICE = "Cyclone II";
  
  wire 		inclock_gated = inclock & inclock_en;
  
  reg [11:0] 	 datain_pos;
  reg [11:0] 	 datain_neg;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      datain_pos <= 12'b0;
    else
      datain_pos <= {datain, datain_pos[11:4]};

  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      datain_neg <= 12'b0;
    else
      datain_neg <= {datain, datain_neg[11:4]};

  reg [4:0] 	 pos_edges;
  reg [4:0] 	 neg_edges;
/* -----\/----- EXCLUDED -----\/-----
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      pos_edges <= 5'b0;
    else
      case (pos_edges)
	5'd15:
	  if (rvere)
	    pos_edges <= pos_edges + 5'd1;
	  else
	    pos_edges <= 5'd0;
	
	5'd17:
	  pos_edges <= 5'd0;

	default:
	  pos_edges <= pos_edges + 5'b1;
      endcase
 -----/\----- EXCLUDED -----/\----- */

  // Following way of coding improves Fmax for pos_edges
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      pos_edges[3:0] <= 4'b0;
    else
      case (pos_edges[3:0])
	4'd1:
	  if (~pos_edges[4])
	    pos_edges[3:0] <= pos_edges[3:0] + 4'd1;
	  else
	    pos_edges[3:0] <= 4'd0;
	
	4'd15:
	  if (rvere)
	    pos_edges[3:0] <= pos_edges[3:0] + 4'd1;
	  else
	    pos_edges[3:0] <= 4'd0;
	
	default:
	  pos_edges[3:0] <= pos_edges[3:0] + 4'b1;
      endcase
  
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      pos_edges[4] <= 1'b0;
    else
      case (pos_edges[3:0])
	4'd0:
	  if (pos_edges[4])
	    pos_edges[4] <= 1'b1;
	  else
	    pos_edges[4] <= 1'b0;
	
	4'd15:
	  if (rvere)
	    pos_edges[4] <= 1'b1;
	  else
	    pos_edges[4] <= 1'b0;
	
	default:
	  pos_edges[4] <= 1'b0;
      endcase

  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      neg_edges <= 5'b0;
    else
      case (neg_edges)
	5'd15:
	  if (rvere)
	    neg_edges <= neg_edges + 5'd1;
	  else
	    neg_edges <= 5'd0;
	
	5'd17:
	  neg_edges <= 5'd0;

	default:
	  neg_edges <= neg_edges + 5'b1;
      endcase


  reg 		 freeze_pos;
  reg 		 freeze_neg;
  always @(posedge inclock_gated)
    freeze_pos <= (pos_edges[1:0] == 2'd2);
      
  always @(negedge inclock_gated)
    freeze_neg <= (neg_edges[1:0] == 2'd2);

  reg [15:0] 	 pos_data;
  reg [15:0] 	 neg_data;
  always @(posedge inclock_gated)
    if (freeze_pos)
      pos_data <= {datain, datain_pos};
 
  always @(negedge inclock_gated)
    if (freeze_neg)
      neg_data <= {datain, datain_neg};
 
  wire [31:0] shift_reg;
  assign shift_reg = {neg_data[15:12], pos_data[15:12],
		      neg_data[11:8], pos_data[11:8],
		      neg_data[7:4], pos_data[7:4],
		      neg_data[3:0], pos_data[3:0]};

  reg 	 data_ready;
  // toggles just before a new quad word is available to give time for
  // synchronisation to local clock domain
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      data_ready <= 1'b0;
    else if (pos_edges[1:0] == 2'd2)
      data_ready <= ~data_ready;

  reg 	 dr_sync1;
  reg 	 dr_sync2;
  reg 	 dr_sync3;
  reg 	 dr_sync4;

  always @(posedge clk or negedge rst_n)
    if (~rst_n)
    begin
      dr_sync1 <= 1'b0;
      dr_sync2 <= 1'b0;
      dr_sync3 <= 1'b0;
      dr_sync4 <= 1'b0;
    end
    else
    begin
      dr_sync1 <= data_ready;
      dr_sync2 <= dr_sync1;
      dr_sync3 <= dr_sync2;
      dr_sync4 <= dr_sync3;
    end

  reg [32:0] fifo_wdata;
  reg blk_end;
  always @(posedge clk or negedge rst_n)
    if (~rst_n)
      fifo_wdata <= 33'b0;
    else if (dr_sync1 ^ dr_sync2)
      fifo_wdata <= {blk_end, shift_reg};

  reg fifo_we;
  always @(posedge clk or negedge rst_n)
    if (~rst_n)
      fifo_we <= 1'b0;
    else
      fifo_we <= dr_sync1 ^ dr_sync2;
  
  wire [32:0] rdata;
  wire [6:0]  wrused;
  dcfifo rx_fifo (
		  .aclr		(~rst_n),
		  
		  .wrclk	(clk),
		  .data		(fifo_wdata),
		  .wrreq	(fifo_we),
		  .wrfull	(),
		  .wrusedw	(wrused),
		  
		  .rdclk	(clk),
		  .rdreq	(rdreq),
		  .q		(rdata),
		  .rdempty	(empty),
		  .rdusedw	()
		  );
	defparam
		rx_fifo.intended_device_family = DEVICE,
		rx_fifo.lpm_width = 33,
		rx_fifo.lpm_numwords = 128,
		rx_fifo.lpm_widthu = 7,
		rx_fifo.clocks_are_synchronized = "FALSE",
		rx_fifo.lpm_type = "dcfifo",
		rx_fifo.lpm_showahead = "OFF",
		rx_fifo.overflow_checking = "ON",
		rx_fifo.underflow_checking = "ON",
		rx_fifo.use_eab = "ON",
		rx_fifo.add_ram_output_register = "OFF",
		rx_fifo.lpm_hint = "RAM_BLOCK_TYPE=AUTO";

  reg 		acko;
  always @(posedge clk or negedge rst_n)
    if (~rst_n)
      acko <= 1'b1;
    else
      if (wrused >= 7'h70)
	acko <= 1'b0;
      else
	acko <= 1'b1;

  // Checksum checking
  reg 		load_ver_l;
  reg 		load_ver_h;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      load_ver_l <= 1'b0;
    else
      load_ver_l <= (pos_edges[4] & ~pos_edges[0]);

  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      load_ver_h <= 1'b0;
    else
      load_ver_h <= (neg_edges[4] & ~neg_edges[0]);

  reg [3:0] 	ver_h;
  reg [3:0] 	ver_l;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      ver_l <= 4'b0;
    else if (load_ver_l)
      ver_l <= datain_pos[11:8];

  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      ver_h <= 4'b0;
    else if (load_ver_h)
      ver_h <= datain_neg[11:8];

  wire [7:0] 	ver_byte;
  assign ver_byte = {ver_h, ver_l};

  reg [1:0] 	words;
  always @(posedge clk or negedge rst_n)
    if (~rst_n)
      words <= 2'h0;
    else if (fifo_we)
      words <= words + 2'h1;

  reg pos_chk_en;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      pos_chk_en <= 1'b0;
    else if (pos_edges[4])
      pos_chk_en <= 1'b0;
    else
      pos_chk_en <= 1'b1;
  
  reg neg_chk_en;
  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      neg_chk_en <= 1'b0;
    else if (neg_edges[4])
      neg_chk_en <= 1'b0;
    else
      neg_chk_en <= 1'b1;
  
/* -----\/----- EXCLUDED -----\/-----
  reg [7:0] low_nibble_chk;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      low_nibble_chk <= 8'b0;
    else if (pos_chk_en)
      low_nibble_chk <= low_nibble_chk + {4'b0, datain_pos[11:8]};
    else
      low_nibble_chk <= 8'b0;
 -----/\----- EXCLUDED -----/\----- */

  // split lower nibble into low_nibble and mid_nibble to avoid an
  // 8 bit adder that will not run at 500MHz
  reg [4:0] low_nibble_chk;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      low_nibble_chk <= 5'b0;
    else if (~pos_chk_en)
      low_nibble_chk <= 5'b0;
    else
      low_nibble_chk <= {1'b0, low_nibble_chk[3:0]} + {1'b0, datain_pos[11:8]};
 
  reg [3:0] mid_nibble_chk;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      mid_nibble_chk <= 4'b0;
    else if (~pos_chk_en)
      mid_nibble_chk <= 4'b0;
    else if (low_nibble_chk[4])
      mid_nibble_chk <= mid_nibble_chk + 1'b1;
 
  reg [7:0] low_nibble_chk_r;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      low_nibble_chk_r <= 8'b0;
    else if (load_ver_l)
      low_nibble_chk_r <= {mid_nibble_chk + {3'b0, low_nibble_chk[4]},
			   low_nibble_chk[3:0]};
 
  reg [3:0] high_nibble_chk;
  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      high_nibble_chk <= 4'b0;
    else if (neg_chk_en)
      high_nibble_chk <= high_nibble_chk + datain_neg[11:8];
    else
      high_nibble_chk <= 4'b0;
 
  reg [3:0] high_nibble_chk_r;
  always @(negedge inclock_gated or negedge rst_n)
    if (~rst_n)
      high_nibble_chk_r <= 4'b0;
    else if (load_ver_h)
      high_nibble_chk_r <= high_nibble_chk;

  wire [7:0] cksum = {high_nibble_chk_r, 4'b0} + low_nibble_chk_r;
  
  reg rcser;
  always @(posedge clk or negedge rst_n)
    if (~rst_n)
      rcser <= 1'b0;
    else if (fifo_we & (&words))
      rcser <= cksum != ver_byte;

  // block complete
  reg bcmp;
  reg bcmpi_sync_n;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
    begin
      bcmpi_sync_n <= 1'b1;
      bcmp <= 1'b0;
    end
    else
    begin
      bcmpi_sync_n <= bcmpi_n;
      bcmp <= ~bcmpi_sync_n;
    end

  reg sample_bcmp;
  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      sample_bcmp <= 1'b0;
    else
      sample_bcmp <= (pos_edges[3:2] == 2'b10);

  always @(posedge inclock_gated or negedge rst_n)
    if (~rst_n)
      blk_end <= 1'b0;
    else if (freeze_pos & ~sample_bcmp)
      blk_end <= 1'b0;
    else if (freeze_pos & sample_bcmp & bcmp)
      blk_end <= 1'b1;
      
endmodule

⌨️ 快捷键说明

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