mor1kx-bemicrocv/ip/altera/ddr3/altera_jtag_dc_streaming.v

262 lines
8.4 KiB
Verilog

// (C) 2001-2015 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files 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 Altera Program License Subscription
// Agreement, Altera MegaCore Function License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the applicable
// agreement for further details.
// This module is a simple clock crosser for control signals. It will take
// the asynchronous control signal and synchronize it to the clk domain
// attached to the clk input. It does so by passing the control signal
// through a pair of registers and then sensing the level transition from
// either hi-to-lo or lo-to-hi. *ATTENTION* This module makes the assumption
// that the control signal will always transition every time is asserted.
// i.e.:
// ____ ___________________
// -> ___| |___ and ___| |_____
//
// on the control signal will be seen as only one assertion of the control
// signal. In short, if your control could be asserted back-to-back, then
// don't use this module. You'll be losing data.
`timescale 1 ns / 1 ns
module altera_jtag_control_signal_crosser (
clk,
reset_n,
async_control_signal,
sense_pos_edge,
sync_control_signal
);
input clk;
input reset_n;
input async_control_signal;
input sense_pos_edge;
output sync_control_signal;
parameter SYNC_DEPTH = 3; // number of synchronizer stages for clock crossing
reg sync_control_signal;
wire synchronized_raw_signal;
reg edge_detector_register;
altera_std_synchronizer #(.depth(SYNC_DEPTH)) synchronizer (
.clk(clk),
.reset_n(reset_n),
.din(async_control_signal),
.dout(synchronized_raw_signal)
);
always @ (posedge clk or negedge reset_n)
if (~reset_n)
edge_detector_register <= 1'b0;
else
edge_detector_register <= synchronized_raw_signal;
always @* begin
if (sense_pos_edge)
sync_control_signal <= ~edge_detector_register & synchronized_raw_signal;
else
sync_control_signal <= edge_detector_register & ~synchronized_raw_signal;
end
endmodule
// This module crosses the clock domain for a given source
module altera_jtag_src_crosser (
sink_clk,
sink_reset_n,
sink_valid,
sink_data,
src_clk,
src_reset_n,
src_valid,
src_data
);
parameter WIDTH = 8;
parameter SYNC_DEPTH = 3; // number of synchronizer stages for clock crossing
input sink_clk;
input sink_reset_n;
input sink_valid;
input [WIDTH-1:0] sink_data;
input src_clk;
input src_reset_n;
output src_valid;
output [WIDTH-1:0] src_data;
reg sink_valid_buffer;
reg [WIDTH-1:0] sink_data_buffer;
reg src_valid;
reg [WIDTH-1:0] src_data /* synthesis ALTERA_ATTRIBUTE = "PRESERVE_REGISTER=ON ; SUPPRESS_DA_RULE_INTERNAL=R101 ; {-from \"*\"} CUT=ON " */;
wire synchronized_valid;
altera_jtag_control_signal_crosser #(
.SYNC_DEPTH(SYNC_DEPTH)
) crosser (
.clk(src_clk),
.reset_n(src_reset_n),
.async_control_signal(sink_valid_buffer),
.sense_pos_edge(1'b1),
.sync_control_signal(synchronized_valid)
);
always @ (posedge sink_clk or negedge sink_reset_n) begin
if (~sink_reset_n) begin
sink_valid_buffer <= 1'b0;
sink_data_buffer <= 'b0;
end else begin
sink_valid_buffer <= sink_valid;
if (sink_valid) begin
sink_data_buffer <= sink_data;
end
end //end if
end //always sink_clk
always @ (posedge src_clk or negedge src_reset_n) begin
if (~src_reset_n) begin
src_valid <= 1'b0;
src_data <= {WIDTH{1'b0}};
end else begin
src_valid <= synchronized_valid;
src_data <= synchronized_valid ? sink_data_buffer : src_data;
end
end
endmodule
module altera_jtag_dc_streaming #(
parameter PURPOSE = 0, // for discovery of services behind this JTAG Phy - 0
// for JTAG Phy, 1 for Packets to Master
parameter UPSTREAM_FIFO_SIZE = 0,
parameter DOWNSTREAM_FIFO_SIZE = 0,
parameter MGMT_CHANNEL_WIDTH = -1
) (
// Signals in the JTAG clock domain
input wire tck,
input wire tdi,
output wire tdo,
input wire [2:0] ir_in,
input wire virtual_state_cdr,
input wire virtual_state_sdr,
input wire virtual_state_udr,
input wire clk,
input wire reset_n,
output wire [7:0] source_data,
output wire source_valid,
input wire [7:0] sink_data,
input wire sink_valid,
output wire sink_ready,
output wire resetrequest,
output wire debug_reset,
output wire mgmt_valid,
output wire [(MGMT_CHANNEL_WIDTH>0?MGMT_CHANNEL_WIDTH:1)-1:0] mgmt_channel,
output wire mgmt_data
);
// the tck to sysclk sync depth is fixed at 8
// 8 is the worst case scenario from our metastability analysis, and since
// using TCK serially is so slow we should have plenty of clock cycles.
localparam TCK_TO_SYSCLK_SYNC_DEPTH = 8;
// The clk to tck path is fixed at 3 deep for Synchronizer depth.
// Since the tck clock is so slow, no parameter is exposed.
localparam SYSCLK_TO_TCK_SYNC_DEPTH = 3;
wire jtag_clock_reset_n; // system reset is synchronized with tck
wire [7:0] jtag_source_data;
wire jtag_source_valid;
wire [7:0] jtag_sink_data;
wire jtag_sink_valid;
wire jtag_sink_ready;
/* Reset Synchronizer module.
*
* The SLD Node does not provide a reset for the TCK clock domain.
* Due to the handshaking nature of the Avalon-ST Clock Crosser,
* internal states need to be reset to 0 in order to guarantee proper
* functionality throughout resets.
*
* This reset block will asynchronously assert reset, and synchronously
* deassert reset for the tck clock domain.
*/
altera_std_synchronizer #(
.depth(SYSCLK_TO_TCK_SYNC_DEPTH)
) synchronizer (
.clk(tck),
.reset_n(reset_n),
.din(1'b1),
.dout(jtag_clock_reset_n)
);
altera_jtag_streaming #(
.PURPOSE(PURPOSE),
.UPSTREAM_FIFO_SIZE(UPSTREAM_FIFO_SIZE),
.DOWNSTREAM_FIFO_SIZE(DOWNSTREAM_FIFO_SIZE),
.MGMT_CHANNEL_WIDTH(MGMT_CHANNEL_WIDTH)
) jtag_streaming (
.tck (tck),
.tdi (tdi),
.tdo (tdo),
.ir_in (ir_in),
.virtual_state_cdr(virtual_state_cdr),
.virtual_state_sdr(virtual_state_sdr),
.virtual_state_udr(virtual_state_udr),
.reset_n(jtag_clock_reset_n),
.source_data(jtag_source_data),
.source_valid(jtag_source_valid),
.sink_data(jtag_sink_data),
.sink_valid(jtag_sink_valid),
.sink_ready(jtag_sink_ready),
.clock_to_sample(clk),
.reset_to_sample(reset_n),
.resetrequest(resetrequest),
.debug_reset(debug_reset),
.mgmt_valid(mgmt_valid),
.mgmt_channel(mgmt_channel),
.mgmt_data(mgmt_data)
);
// synchronization in both clock domain crossings takes place in the "clk" system clock domain!
altera_avalon_st_clock_crosser #(
.SYMBOLS_PER_BEAT(1),
.BITS_PER_SYMBOL(8),
.FORWARD_SYNC_DEPTH(SYSCLK_TO_TCK_SYNC_DEPTH),
.BACKWARD_SYNC_DEPTH(TCK_TO_SYSCLK_SYNC_DEPTH)
) sink_crosser (
.in_clk(clk),
.in_reset(~reset_n),
.in_data(sink_data),
.in_ready(sink_ready),
.in_valid(sink_valid),
.out_clk(tck),
.out_reset(~jtag_clock_reset_n),
.out_data(jtag_sink_data),
.out_ready(jtag_sink_ready),
.out_valid(jtag_sink_valid)
);
altera_jtag_src_crosser #(
.SYNC_DEPTH(TCK_TO_SYSCLK_SYNC_DEPTH)
) source_crosser (
.sink_clk(tck),
.sink_reset_n(jtag_clock_reset_n),
.sink_valid(jtag_source_valid),
.sink_data(jtag_source_data),
.src_clk(clk),
.src_reset_n(reset_n),
.src_valid(source_valid),
.src_data(source_data)
);
endmodule