Visible to Intel only — GUID: tdh1629932832406
Ixiasoft
1.1. Using Provided HDL Templates
1.2. Instantiating IP Cores in HDL
1.3. Inferring Multipliers and DSP Functions
1.4. Inferring Memory Functions from HDL Code
1.5. Register and Latch Coding Guidelines
1.6. General Coding Guidelines
1.7. Designing with Low-Level Primitives
1.8. Recommended HDL Coding Styles Revision History
1.4.1.1. Use Synchronous Memory Blocks
1.4.1.2. Avoid Unsupported Reset and Control Conditions
1.4.1.3. Check Read-During-Write Behavior
1.4.1.4. Controlling RAM Inference and Implementation
1.4.1.5. Single-Clock Synchronous RAM with Old Data Read-During-Write Behavior
1.4.1.6. Single-Clock Synchronous RAM with New Data Read-During-Write Behavior
1.4.1.7. Simple Dual-Port, Dual-Clock Synchronous RAM
1.4.1.8. True Dual-Port Synchronous RAM
1.4.1.9. Mixed-Width Dual-Port RAM
1.4.1.10. RAM with Byte-Enable Signals
1.4.1.11. Specifying Initial Memory Contents at Power-Up
1.6.6.1. If Performance is Important, Optimize for Speed
1.6.6.2. Use Separate CRC Blocks Instead of Cascaded Stages
1.6.6.3. Use Separate CRC Blocks Instead of Allowing Blocks to Merge
1.6.6.4. Take Advantage of Latency if Available
1.6.6.5. Save Power by Disabling CRC Blocks When Not in Use
1.6.6.6. Initialize the Device with the Synchronous Load (sload) Signal
3.4.1. Apply Complete System-Centric Timing Constraints for the Timing Analyzer
3.4.2. Force the Identification of Synchronization Registers
3.4.3. Set the Synchronizer Data Toggle Rate
3.4.4. Optimize Metastability During Fitting
3.4.5. Increase the Length of Synchronizers to Protect and Optimize
3.4.6. Increase the Number of Stages Used in Synchronizers
3.4.7. Select a Faster Speed Grade Device
Visible to Intel only — GUID: tdh1629932832406
Ixiasoft
1.4.4.1. Dual Clock FIFO Example in Verilog HDL
// Copyright 2021 Intel Corporation.
//
// This reference design file is subject licensed to you by the terms and
// conditions of the applicable License Terms and Conditions for Hardware
// Reference Designs and/or Design Examples (either as signed by you or
// found at https://www.altera.com/common/legal/leg-license_agreement.html ).
//
// As stated in the license, you agree to only use this reference design
// solely in conjunction with Intel FPGAs or Intel CPLDs.
//
// THE REFERENCE DESIGN IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY,
// NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. Intel does not
// warrant or assume responsibility for the accuracy or completeness of any
// information, links or other items within the Reference Design and any
// accompanying materials.
//
// In the event that you do not agree with such terms and conditions, do not
// use the reference design file.
/////////////////////////////////////////////////////////////////////////////
module dcfifo_example
#(
parameter LOG_DEPTH = 5,
parameter WIDTH = 20,
parameter ALMOST_FULL_VALUE = 30,
parameter ALMOST_EMPTY_VALUE = 2,
parameter NUM_WORDS = 2**LOG_DEPTH - 1,
parameter OVERFLOW_CHECKING = 0, // Overflow checking circuitry is \
using extra area. Use only if you need it
parameter UNDERFLOW_CHECKING = 0 // Underflow checking circuitry is \
using extra area. Use only if you need it
)
(
input aclr,
input wrclk,
input wrreq,
input [WIDTH-1:0] data,
output reg wrempty,
output reg wrfull,
output reg wr_almost_empty,
output reg wr_almost_full,
output [LOG_DEPTH-1:0] wrusedw,
input rdclk,
input rdreq,
output [WIDTH-1:0] q,
output reg rdempty,
output reg rdfull,
output reg rd_almost_empty,
output reg rd_almost_full,
output [LOG_DEPTH-1:0] rdusedw
);
initial begin
if ((LOG_DEPTH > 5) || (LOG_DEPTH < 3))
$error("Invalid parameter value: LOG_DEPTH = %0d; valid range is 2 \
< LOG_DEPTH < 6", LOG_DEPTH);
if ((ALMOST_FULL_VALUE > 2 ** LOG_DEPTH - 1) || (ALMOST_FULL_VALUE < 1))
$error("Incorrect parameter value: ALMOST_FULL_VALUE = %0d; valid \
range is 0 < ALMOST_FULL_VALUE < %0d",
ALMOST_FULL_VALUE, 2 ** LOG_DEPTH);
if ((ALMOST_EMPTY_VALUE > 2 ** LOG_DEPTH - 1) || (ALMOST_EMPTY_VALUE < 1))
$error("Incorrect parameter value: ALMOST_EMPTY_VALUE = %0d; valid \
range is 0 < ALMOST_EMPTY_VALUE < %0d",
ALMOST_EMPTY_VALUE, 2 ** LOG_DEPTH);
if ((NUM_WORDS > 2 ** LOG_DEPTH - 1) || (NUM_WORDS < 1))
$error("Incorrect parameter value: NUM_WORDS = %0d; \
valid range is 0 < NUM_WORDS < %0d",
NUM_WORDS, 2 ** LOG_DEPTH);
end
(* altera_attribute = "-name AUTO_CLOCK_ENABLE_RECOGNITION OFF" *) reg \
[LOG_DEPTH-1:0] write_addr = 0;
(* altera_attribute = "-name AUTO_CLOCK_ENABLE_RECOGNITION OFF" *) reg \
[LOG_DEPTH-1:0] read_addr = 0;
reg [LOG_DEPTH-1:0] wrcapacity = 0;
reg [LOG_DEPTH-1:0] rdcapacity = 0;
wire [LOG_DEPTH-1:0] wrcapacity_w;
wire [LOG_DEPTH-1:0] rdcapacity_w;
wire [LOG_DEPTH-1:0] rd_write_addr;
wire [LOG_DEPTH-1:0] wr_read_addr;
wire wrreq_safe;
wire rdreq_safe;
assign wrreq_safe = OVERFLOW_CHECKING ? wrreq & ~wrfull : wrreq;
assign rdreq_safe = UNDERFLOW_CHECKING ? rdreq & ~rdempty : rdreq;
initial begin
write_addr = 0;
read_addr = 0;
wrempty = 1;
wrfull = 0;
rdempty = 1;
rdfull = 0;
wrcapacity = 0;
rdcapacity = 0;
rd_almost_empty = 1;
rd_almost_full = 0;
wr_almost_empty = 1;
wr_almost_full = 0;
end
// ------------------ Write -------------------------
add_a_b_s0_s1 #(LOG_DEPTH) wr_adder(
.a(write_addr),
.b(~wr_read_addr),
.s0(wrreq_safe),
.s1(1'b1),
.out(wrcapacity_w)
);
always @(posedge wrclk or posedge aclr) begin
if (aclr) begin
write_addr <= 0;
wrcapacity <= 0;
wrempty <= 1;
wrfull <= 0;
wr_almost_full <= 0;
wr_almost_empty <= 1;
end else begin
write_addr <= write_addr + wrreq_safe;
wrcapacity <= wrcapacity_w;
wrempty <= (wrcapacity == 0) && (wrreq == 0);
wrfull <= (wrcapacity == NUM_WORDS) || (wrcapacity == NUM_WORDS - 1) \
&& (wrreq == 1);
wr_almost_empty <=
(wrcapacity < (ALMOST_EMPTY_VALUE-1)) ||
(wrcapacity == (ALMOST_EMPTY_VALUE-1)) && (wrreq == 0);
wr_almost_full <=
(wrcapacity >= ALMOST_FULL_VALUE) ||
(wrcapacity == ALMOST_FULL_VALUE - 1) && (wrreq == 1);
end
end
assign wrusedw = wrcapacity;
// ------------------ Read -------------------------
add_a_b_s0_s1 #(LOG_DEPTH) rd_adder(
.a(rd_write_addr),
.b(~read_addr),
.s0(1'b0),
.s1(~rdreq_safe),
.out(rdcapacity_w)
);
always @(posedge rdclk or posedge aclr) begin
if (aclr) begin
read_addr <= 0;
rdcapacity <= 0;
rdempty <= 1;
rdfull <= 0;
rd_almost_empty <= 1;
rd_almost_full <= 0;
end else begin
read_addr <= read_addr + rdreq_safe;
rdcapacity <= rdcapacity_w;
rdempty <= (rdcapacity == 0) || (rdcapacity == 1) && (rdreq == 1);
rdfull <= (rdcapacity == NUM_WORDS) && (rdreq == 0);
rd_almost_empty <=
(rdcapacity < ALMOST_EMPTY_VALUE) ||
(rdcapacity == ALMOST_EMPTY_VALUE) && (rdreq == 1);
rd_almost_full <=
(rdcapacity > ALMOST_FULL_VALUE) ||
(rdcapacity == ALMOST_FULL_VALUE) && (rdreq == 0);
end
end
assign rdusedw = rdcapacity;
// ---------------- Synchronizers --------------------
wire [LOG_DEPTH-1:0] gray_read_addr;
wire [LOG_DEPTH-1:0] wr_gray_read_addr;
wire [LOG_DEPTH-1:0] gray_write_addr;
wire [LOG_DEPTH-1:0] rd_gray_write_addr;
binary_to_gray #(.WIDTH(LOG_DEPTH)) rd_b2g (.clock(rdclk), .aclr(aclr), \
.din(read_addr), .dout(gray_read_addr));
synchronizer_ff_r2 #(.WIDTH(LOG_DEPTH)) rd2wr (.din_clk(rdclk), .din(gray_read_addr), \
.dout_clk(wrclk), .dout(wr_gray_read_addr));
gray_to_binary #(.WIDTH(LOG_DEPTH)) rd_g2b (.clock(wrclk), .aclr(aclr), \
.din(wr_gray_read_addr), .dout(wr_read_addr));
binary_to_gray #(.WIDTH(LOG_DEPTH)) wr_b2g (.clock(wrclk), .aclr(aclr), .din(write_addr), \
.dout(gray_write_addr));
synchronizer_ff_r2 #(.WIDTH(LOG_DEPTH)) wr2rd (.din_clk(wrclk), .din(gray_write_addr), \
.dout_clk(rdclk), .dout(rd_gray_write_addr));
gray_to_binary #(.WIDTH(LOG_DEPTH)) wr_g2b (.clock(rdclk), .aclr(aclr), \
.din(rd_gray_write_addr), .dout(rd_write_addr));
// ------------------ MLAB ---------------------------
generic_mlab_dc #(.WIDTH(WIDTH), .ADDR_WIDTH(LOG_DEPTH)) mlab_inst (
.rclk(rdclk),
.wclk(wrclk),
.din(data),
.waddr(write_addr),
.we(1'b1),
.re(1'b1),
.raddr(read_addr),
.dout(q)
);
endmodule
module add_a_b_s0_s1 #(
parameter SIZE = 5
)(
input [SIZE-1:0] a,
input [SIZE-1:0] b,
input s0,
input s1,
output [SIZE-1:0] out
);
wire [SIZE:0] left;
wire [SIZE:0] right;
wire temp;
assign left = {a ^ b, s0};
assign right = {a[SIZE-2:0] & b[SIZE-2:0], s1, s0};
assign {out, temp} = left + right;
endmodule
module binary_to_gray #(
parameter WIDTH = 5
) (
input clock,
input aclr,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
always @(posedge clock or posedge aclr) begin
if (aclr)
dout <= 0;
else
dout <= din ^ (din >> 1);
end
endmodule
module gray_to_binary #(
parameter WIDTH = 5
) (
input clock,
input aclr,
input [WIDTH-1:0] din,
output reg [WIDTH-1:0] dout
);
wire [WIDTH-1:0] dout_w;
genvar i;
generate
for (i = 0; i < WIDTH; i=i+1) begin : loop
assign dout_w[i] = ^(din[WIDTH-1:i]);
end
endgenerate
always @(posedge clock or posedge aclr) begin
if (aclr)
dout <= 0;
else
dout <= dout_w;
end
endmodule
(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION OFF" *)
module generic_mlab_dc #(
parameter WIDTH = 8,
parameter ADDR_WIDTH = 5
)(
input rclk,
input wclk,
input [WIDTH-1:0] din,
input [ADDR_WIDTH-1:0] waddr,
input we,
input re,
input [ADDR_WIDTH-1:0] raddr,
output [WIDTH-1:0] dout
);
localparam DEPTH = 1 << ADDR_WIDTH;
(* ramstyle = "mlab" *) reg [WIDTH-1:0] mem[0:DEPTH-1];
reg [WIDTH-1:0] dout_r;
always @(posedge wclk) begin
if (we)
mem[waddr] <= din;
end
always @(posedge rclk) begin
if (re)
dout_r <= mem[raddr];
end
assign dout = dout_r;
endmodule
module synchronizer_ff_r2 #(
parameter WIDTH = 8
)(
input din_clk,
input [WIDTH-1:0] din,
input dout_clk,
output [WIDTH-1:0] dout
);
reg [WIDTH-1:0] ff_launch = {WIDTH {1'b0}}
/* synthesis preserve dont_replicate */;
always @(posedge din_clk) begin
ff_launch <= din;
end
reg [WIDTH-1:0] ff_meta = {WIDTH {1'b0}}
/* synthesis preserve dont_replicate */;
always @(posedge dout_clk) begin
ff_meta <= ff_launch;
end
reg [WIDTH-1:0] ff_sync = {WIDTH {1'b0}}
/* synthesis preserve dont_replicate */;
always @(posedge dout_clk) begin
ff_sync <= ff_meta;
end
assign dout = ff_sync;
endmodule