219 lines
7.4 KiB
Verilog
219 lines
7.4 KiB
Verilog
// (C) 2001-2018 Intel Corporation. All rights reserved.
|
|
// Your use of Intel Corporation's design tools, logic functions and other
|
|
// software and tools, and its AMPP partner logic functions, and any output
|
|
// files from any of the foregoing (including device programming or simulation
|
|
// files), and any associated documentation or information are expressly subject
|
|
// to the terms and conditions of the Intel Program License Subscription
|
|
// Agreement, Intel FPGA IP License Agreement, or other applicable
|
|
// license agreement, including, without limitation, that your use is for the
|
|
// sole purpose of programming logic devices manufactured by Intel and sold by
|
|
// Intel or its authorized distributors. Please refer to the applicable
|
|
// agreement for further details.
|
|
|
|
|
|
// $File: //acds/rel/18.1std/ip/avalon_st/altera_avalon_st_handshake_clock_crosser/altera_avalon_st_handshake_clock_crosser.v $
|
|
// $Revision: #1 $
|
|
// $Date: 2018/07/18 $
|
|
// $Author: psgswbuild $
|
|
//------------------------------------------------------------------------------
|
|
// Clock crosser module with handshaking mechanism
|
|
//------------------------------------------------------------------------------
|
|
|
|
`timescale 1ns / 1ns
|
|
|
|
module altera_avalon_st_handshake_clock_crosser
|
|
#(
|
|
parameter DATA_WIDTH = 8,
|
|
BITS_PER_SYMBOL = 8,
|
|
USE_PACKETS = 0,
|
|
|
|
// ------------------------------
|
|
// Optional signal widths
|
|
// ------------------------------
|
|
USE_CHANNEL = 0,
|
|
CHANNEL_WIDTH = 1,
|
|
USE_ERROR = 0,
|
|
ERROR_WIDTH = 1,
|
|
|
|
VALID_SYNC_DEPTH = 2,
|
|
READY_SYNC_DEPTH = 2,
|
|
|
|
USE_OUTPUT_PIPELINE = 1,
|
|
|
|
// ------------------------------
|
|
// Derived parameters
|
|
// ------------------------------
|
|
SYMBOLS_PER_BEAT = DATA_WIDTH / BITS_PER_SYMBOL,
|
|
EMPTY_WIDTH = log2ceil(SYMBOLS_PER_BEAT)
|
|
)
|
|
(
|
|
input in_clk,
|
|
input in_reset,
|
|
input out_clk,
|
|
input out_reset,
|
|
|
|
output in_ready,
|
|
input in_valid,
|
|
input [DATA_WIDTH - 1 : 0] in_data,
|
|
input [CHANNEL_WIDTH - 1 : 0] in_channel,
|
|
input [ERROR_WIDTH - 1 : 0] in_error,
|
|
input in_startofpacket,
|
|
input in_endofpacket,
|
|
input [(EMPTY_WIDTH ? (EMPTY_WIDTH - 1) : 0) : 0] in_empty,
|
|
|
|
input out_ready,
|
|
output out_valid,
|
|
output [DATA_WIDTH - 1 : 0] out_data,
|
|
output [CHANNEL_WIDTH - 1 : 0] out_channel,
|
|
output [ERROR_WIDTH - 1 : 0] out_error,
|
|
output out_startofpacket,
|
|
output out_endofpacket,
|
|
output [(EMPTY_WIDTH ? (EMPTY_WIDTH - 1) : 0) : 0] out_empty
|
|
);
|
|
|
|
// ------------------------------
|
|
// Payload-specific widths
|
|
// ------------------------------
|
|
localparam PACKET_WIDTH = (USE_PACKETS) ? 2 + EMPTY_WIDTH : 0;
|
|
localparam PCHANNEL_W = (USE_CHANNEL) ? CHANNEL_WIDTH : 0;
|
|
localparam PERROR_W = (USE_ERROR) ? ERROR_WIDTH : 0;
|
|
|
|
localparam PAYLOAD_WIDTH = DATA_WIDTH +
|
|
PACKET_WIDTH +
|
|
PCHANNEL_W +
|
|
EMPTY_WIDTH +
|
|
PERROR_W;
|
|
|
|
|
|
wire [PAYLOAD_WIDTH - 1: 0] in_payload;
|
|
wire [PAYLOAD_WIDTH - 1: 0] out_payload;
|
|
|
|
// ------------------------------
|
|
// Assign in_data and other optional sink interface
|
|
// signals to in_payload.
|
|
// ------------------------------
|
|
assign in_payload[DATA_WIDTH - 1 : 0] = in_data;
|
|
generate
|
|
// optional packet inputs
|
|
if (PACKET_WIDTH) begin
|
|
assign in_payload[
|
|
DATA_WIDTH + PACKET_WIDTH - 1 :
|
|
DATA_WIDTH
|
|
] = {in_startofpacket, in_endofpacket};
|
|
end
|
|
// optional channel input
|
|
if (USE_CHANNEL) begin
|
|
assign in_payload[
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W - 1 :
|
|
DATA_WIDTH + PACKET_WIDTH
|
|
] = in_channel;
|
|
end
|
|
// optional empty input
|
|
if (EMPTY_WIDTH) begin
|
|
assign in_payload[
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W + EMPTY_WIDTH - 1 :
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W
|
|
] = in_empty;
|
|
end
|
|
// optional error input
|
|
if (USE_ERROR) begin
|
|
assign in_payload[
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W + EMPTY_WIDTH + PERROR_W - 1 :
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W + EMPTY_WIDTH
|
|
] = in_error;
|
|
end
|
|
endgenerate
|
|
|
|
// --------------------------------------------------
|
|
// Pipe the input payload to our inner module which handles the
|
|
// actual clock crossing
|
|
// --------------------------------------------------
|
|
altera_avalon_st_clock_crosser
|
|
#(
|
|
.SYMBOLS_PER_BEAT (1),
|
|
.BITS_PER_SYMBOL (PAYLOAD_WIDTH),
|
|
.FORWARD_SYNC_DEPTH (VALID_SYNC_DEPTH),
|
|
.BACKWARD_SYNC_DEPTH (READY_SYNC_DEPTH),
|
|
.USE_OUTPUT_PIPELINE (USE_OUTPUT_PIPELINE)
|
|
) clock_xer (
|
|
.in_clk (in_clk ),
|
|
.in_reset (in_reset ),
|
|
.in_ready (in_ready ),
|
|
.in_valid (in_valid ),
|
|
.in_data (in_payload ),
|
|
.out_clk (out_clk ),
|
|
.out_reset (out_reset ),
|
|
.out_ready (out_ready ),
|
|
.out_valid (out_valid ),
|
|
.out_data (out_payload )
|
|
);
|
|
|
|
// --------------------------------------------------
|
|
// Split out_payload into the output signals.
|
|
// --------------------------------------------------
|
|
assign out_data = out_payload[DATA_WIDTH - 1 : 0];
|
|
|
|
generate
|
|
// optional packet outputs
|
|
if (USE_PACKETS) begin
|
|
assign {out_startofpacket, out_endofpacket} =
|
|
out_payload[DATA_WIDTH + PACKET_WIDTH - 1 : DATA_WIDTH];
|
|
end else begin
|
|
// avoid a "has no driver" warning.
|
|
assign {out_startofpacket, out_endofpacket} = 2'b0;
|
|
end
|
|
|
|
// optional channel output
|
|
if (USE_CHANNEL) begin
|
|
assign out_channel = out_payload[
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W - 1 :
|
|
DATA_WIDTH + PACKET_WIDTH
|
|
];
|
|
end else begin
|
|
// avoid a "has no driver" warning.
|
|
assign out_channel = 1'b0;
|
|
end
|
|
|
|
// optional empty output
|
|
if (EMPTY_WIDTH) begin
|
|
assign out_empty = out_payload[
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W + EMPTY_WIDTH - 1 :
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W
|
|
];
|
|
end else begin
|
|
// avoid a "has no driver" warning.
|
|
assign out_empty = 1'b0;
|
|
end
|
|
|
|
// optional error output
|
|
if (USE_ERROR) begin
|
|
assign out_error = out_payload[
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W + EMPTY_WIDTH + PERROR_W - 1 :
|
|
DATA_WIDTH + PACKET_WIDTH + PCHANNEL_W + EMPTY_WIDTH
|
|
];
|
|
end else begin
|
|
// avoid a "has no driver" warning.
|
|
assign out_error = 1'b0;
|
|
end
|
|
endgenerate
|
|
|
|
// --------------------------------------------------
|
|
// Calculates the log2ceil of the input value.
|
|
// --------------------------------------------------
|
|
function integer log2ceil;
|
|
input integer val;
|
|
integer i;
|
|
|
|
begin
|
|
i = 1;
|
|
log2ceil = 0;
|
|
|
|
while (i < val) begin
|
|
log2ceil = log2ceil + 1;
|
|
i = i << 1;
|
|
end
|
|
end
|
|
endfunction
|
|
|
|
endmodule
|