Skip to content

Commit 803c939

Browse files
committed
add ip-less option for non intel/xilinx
This is the same implementation used in v1.1 but with added ip-less ddr io. Hopefully it covers lattice and others but I don't know enough about those to confirm.
1 parent 33b8a60 commit 803c939

File tree

1 file changed

+105
-47
lines changed

1 file changed

+105
-47
lines changed

src/serializer.sv

Lines changed: 105 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -136,53 +136,111 @@ module serializer
136136
position <= position == 4'd9 ? 4'd0 : position + 1'd1;
137137
end
138138
`else
139-
altlvds_tx ALTLVDS_TX_component (
140-
.tx_in ({10'b1111100000, tmds_reversed[2], tmds_reversed[1], tmds_reversed[0]}),
141-
.tx_inclock (clk_pixel_x5),
142-
.tx_out ({tmds_clock, tmds[2], tmds[1], tmds[0]}),
143-
.tx_outclock (),
144-
.pll_areset (1'b0),
145-
.sync_inclock (1'b0),
146-
.tx_coreclock (),
147-
.tx_data_reset (reset),
148-
.tx_enable (1'b1),
149-
.tx_locked (),
150-
.tx_pll_enable (1'b1),
151-
.tx_syncclock (clk_pixel));
152-
defparam
153-
ALTLVDS_TX_component.center_align_msb = "UNUSED",
154-
ALTLVDS_TX_component.common_rx_tx_pll = "OFF",
155-
ALTLVDS_TX_component.coreclock_divide_by = 1,
156-
// ALTLVDS_TX_component.data_rate = "800.0 Mbps",
157-
ALTLVDS_TX_component.deserialization_factor = 10,
158-
ALTLVDS_TX_component.differential_drive = 0,
159-
ALTLVDS_TX_component.enable_clock_pin_mode = "UNUSED",
160-
ALTLVDS_TX_component.implement_in_les = "OFF",
161-
ALTLVDS_TX_component.inclock_boost = 0,
162-
ALTLVDS_TX_component.inclock_data_alignment = "EDGE_ALIGNED",
163-
ALTLVDS_TX_component.inclock_period = int'(10000000.0 / (VIDEO_RATE * 10.0)),
164-
ALTLVDS_TX_component.inclock_phase_shift = 0,
165-
// ALTLVDS_TX_component.intended_device_family = "Cyclone V",
166-
ALTLVDS_TX_component.lpm_hint = "CBX_MODULE_PREFIX=altlvds_tx_inst",
167-
ALTLVDS_TX_component.lpm_type = "altlvds_tx",
168-
ALTLVDS_TX_component.multi_clock = "OFF",
169-
ALTLVDS_TX_component.number_of_channels = 4,
170-
// ALTLVDS_TX_component.outclock_alignment = "EDGE_ALIGNED",
171-
// ALTLVDS_TX_component.outclock_divide_by = 1,
172-
// ALTLVDS_TX_component.outclock_duty_cycle = 50,
173-
// ALTLVDS_TX_component.outclock_multiply_by = 1,
174-
// ALTLVDS_TX_component.outclock_phase_shift = 0,
175-
// ALTLVDS_TX_component.outclock_resource = "Dual-Regional clock",
176-
ALTLVDS_TX_component.output_data_rate = int'(VIDEO_RATE * 10.0),
177-
ALTLVDS_TX_component.pll_compensation_mode = "AUTO",
178-
ALTLVDS_TX_component.pll_self_reset_on_loss_lock = "OFF",
179-
ALTLVDS_TX_component.preemphasis_setting = 0,
180-
// ALTLVDS_TX_component.refclk_frequency = "20.000000 MHz",
181-
ALTLVDS_TX_component.registered_input = "OFF",
182-
ALTLVDS_TX_component.use_external_pll = "ON",
183-
ALTLVDS_TX_component.use_no_phase_shift = "ON",
184-
ALTLVDS_TX_component.vod_setting = 0,
185-
ALTLVDS_TX_component.clk_src_is_pll = "off";
139+
`ifdef ALTERA_RESERVED_QIS
140+
altlvds_tx ALTLVDS_TX_component (
141+
.tx_in ({10'b1111100000, tmds_reversed[2], tmds_reversed[1], tmds_reversed[0]}),
142+
.tx_inclock (clk_pixel_x5),
143+
.tx_out ({tmds_clock, tmds[2], tmds[1], tmds[0]}),
144+
.tx_outclock (),
145+
.pll_areset (1'b0),
146+
.sync_inclock (1'b0),
147+
.tx_coreclock (),
148+
.tx_data_reset (reset),
149+
.tx_enable (1'b1),
150+
.tx_locked (),
151+
.tx_pll_enable (1'b1),
152+
.tx_syncclock (clk_pixel));
153+
defparam
154+
ALTLVDS_TX_component.center_align_msb = "UNUSED",
155+
ALTLVDS_TX_component.common_rx_tx_pll = "OFF",
156+
ALTLVDS_TX_component.coreclock_divide_by = 1,
157+
// ALTLVDS_TX_component.data_rate = "800.0 Mbps",
158+
ALTLVDS_TX_component.deserialization_factor = 10,
159+
ALTLVDS_TX_component.differential_drive = 0,
160+
ALTLVDS_TX_component.enable_clock_pin_mode = "UNUSED",
161+
ALTLVDS_TX_component.implement_in_les = "OFF",
162+
ALTLVDS_TX_component.inclock_boost = 0,
163+
ALTLVDS_TX_component.inclock_data_alignment = "EDGE_ALIGNED",
164+
ALTLVDS_TX_component.inclock_period = int'(10000000.0 / (VIDEO_RATE * 10.0)),
165+
ALTLVDS_TX_component.inclock_phase_shift = 0,
166+
// ALTLVDS_TX_component.intended_device_family = "Cyclone V",
167+
ALTLVDS_TX_component.lpm_hint = "CBX_MODULE_PREFIX=altlvds_tx_inst",
168+
ALTLVDS_TX_component.lpm_type = "altlvds_tx",
169+
ALTLVDS_TX_component.multi_clock = "OFF",
170+
ALTLVDS_TX_component.number_of_channels = 4,
171+
// ALTLVDS_TX_component.outclock_alignment = "EDGE_ALIGNED",
172+
// ALTLVDS_TX_component.outclock_divide_by = 1,
173+
// ALTLVDS_TX_component.outclock_duty_cycle = 50,
174+
// ALTLVDS_TX_component.outclock_multiply_by = 1,
175+
// ALTLVDS_TX_component.outclock_phase_shift = 0,
176+
// ALTLVDS_TX_component.outclock_resource = "Dual-Regional clock",
177+
ALTLVDS_TX_component.output_data_rate = int'(VIDEO_RATE * 10.0),
178+
ALTLVDS_TX_component.pll_compensation_mode = "AUTO",
179+
ALTLVDS_TX_component.pll_self_reset_on_loss_lock = "OFF",
180+
ALTLVDS_TX_component.preemphasis_setting = 0,
181+
// ALTLVDS_TX_component.refclk_frequency = "20.000000 MHz",
182+
ALTLVDS_TX_component.registered_input = "OFF",
183+
ALTLVDS_TX_component.use_external_pll = "ON",
184+
ALTLVDS_TX_component.use_no_phase_shift = "ON",
185+
ALTLVDS_TX_component.vod_setting = 0,
186+
ALTLVDS_TX_component.clk_src_is_pll = "off";
187+
`else
188+
// We don't know what the platform is so the best bet is an IP-less implementation.
189+
// Shift registers are loaded with a set of values from tmds_channels every clk_pixel.
190+
// They are shifted out on clk_pixel_x5 by the time the next set is loaded.
191+
logic [9:0] tmds_shift [NUM_CHANNELS-1:0] = '{10'd0, 10'd0, 10'd0};
192+
193+
logic tmds_control = 1'd0;
194+
always_ff @(posedge clk_pixel)
195+
tmds_control <= !tmds_control;
196+
197+
logic [3:0] tmds_control_synchronizer_chain = 4'd0;
198+
always_ff @(posedge clk_pixel_x5)
199+
tmds_control_synchronizer_chain <= {tmds_control, tmds_control_synchronizer_chain[3:1]};
200+
201+
logic load;
202+
assign load = tmds_control_synchronizer_chain[1] ^ tmds_control_synchronizer_chain[0];
203+
logic [9:0] tmds_mux [NUM_CHANNELS-1:0];
204+
always_comb
205+
begin
206+
if (load)
207+
tmds_mux = tmds_internal;
208+
else
209+
tmds_mux = tmds_shift;
210+
end
211+
212+
// See Section 5.4.1
213+
for (i = 0; i < NUM_CHANNELS; i++)
214+
begin: tmds_shifting
215+
always_ff @(posedge clk_pixel_x5)
216+
tmds_shift[i] <= load ? tmds_mux[i] : tmds_shift[i] >> 2;
217+
end
218+
219+
logic [9:0] tmds_shift_clk_pixel = 10'b0000011111;
220+
always_ff @(posedge clk_pixel_x5)
221+
tmds_shift_clk_pixel <= load ? 10'b0000011111 : {tmds_shift_clk_pixel[1:0], tmds_shift_clk_pixel[9:2]};
222+
223+
logic [NUM_CHANNELS-1:0] tmds_shift_negedge_temp;
224+
for (i = 0; i < NUM_CHANNELS; i++)
225+
begin: tmds_driving
226+
always_ff @(posedge clk_pixel_x5)
227+
begin
228+
tmds[i] <= tmds_shift[i][0];
229+
tmds_shift_negedge_temp[i] <= tmds_shift[i][1];
230+
end
231+
always_ff @(negedge clk_pixel_x5)
232+
tmds[i] <= tmds_shift_negedge_temp[i];
233+
end
234+
logic tmds_clock_negedge_temp;
235+
always_ff @(posedge clk_pixel_x5)
236+
begin
237+
tmds_clock <= tmds_shift_clk_pixel[0];
238+
tmds_clock_negedge_temp <= tmds_shift_clk_pixel[1];
239+
end
240+
always_ff @(negedge clk_pixel_x5)
241+
tmds_clock <= tmds_shift_negedge_temp;
242+
243+
`endif
186244
`endif
187245
`endif
188246
`endif

0 commit comments

Comments
 (0)