Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Безглитчевый мультиплексор клоков
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
des00
Добрый день господа!
Нужно сделать переключение 4-х клоков, без глитча во время переключения. Это можно сделать с помощью одного мультиплексора 4-в-1 вида
CODE

module clock_switcher4clock
(
clkina ,
clkinb ,
clkinc ,
clkind ,
sel , // clkout = (sel == 0/1/2/3) -> clkina/clkinb/clkinc/clkind
clkout
);

//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------

input logic clkina;
input logic clkinb;
input logic clkinc;
input logic clkind;
input logic [1 : 0] sel ; // clkout = (sel == 0/1/2/3) -> clkina/clkinb/clkinc/clkind
output logic clkout;

//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------

logic ctrla;
logic ctrlb;
logic ctrlc;
logic ctrld;

logic [1:0] muxa;
logic [1:0] muxb;
logic [1:0] muxc;
logic [1:0] muxd;

//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------
// synthesis translate_off
initial begin : ini
muxa = '0;
muxb = '0;
muxc = '0;
muxd = '0;
end
// synthesis translate_on
//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------

assign ctrla = ~sel[1] & ~sel[0] & ~muxb[1] & ~muxc[1] & ~muxd[1];
assign ctrlb = ~sel[1] & sel[0] & ~muxa[1] & ~muxc[1] & ~muxd[1];
assign ctrlc = sel[1] & ~sel[0] & ~muxa[1] & ~muxb[1] & ~muxd[1] ;
assign ctrld = sel[1] & sel[0] & ~muxa[1] & ~muxb[1] & ~muxc[1];


always_ff @(negedge clkina) begin
muxa <= {muxa[0], ctrla};
end

always_ff @(negedge clkinb) begin
muxb <= {muxb[0], ctrlb};
end

always_ff @(negedge clkinc) begin
muxc <= {muxc[0], ctrlc};
end

always_ff @(negedge clkind ) begin
muxd <= {muxd[0], ctrld};
end

assign clkout = (muxa[1] & clkina) | (muxb[1] & clkinb) | (muxc[1] & clkinc) | (muxd[1] & clkind);

endmodule

или с помошью четырех мультиплексоров 2-в-1 вида
CODE

assign ctrla = ~sel & ~muxb[1];
assign ctrlb = sel & ~muxa[1];

always_ff @(negedge clkina) begin
muxa <= {muxa[0], ctrla};
end

always_ff @(negedge clkinb) begin
muxb <= {muxb[0], ctrlb};
end

assign clkout = (muxa[1] & clkina) | (muxb[1] & clkinb);

Мне кажеться что оба варианта должны быть работоспособны, но может быть я ошибаюсь. Подскажите какой вариант является более правильным?
ЗЫ. Вариант использовать альтеровскую корку не предлагать, она не может покрыть всех вариантов используемых клоков %)
SM
Более правильный вариант вообще третий, до четырех клоков расширяется по аналогии smile.gif

Код
reg [1:0] clock_selector;
reg [1:0] loclk_dly;
reg [1:0] hiclk_dly;
reg [1:0] intclk_dly;

wire outclk;

always @(negedge lo_clk or posedge hw_reset)
  if (hw_reset) loclk_dly <= 2'b00; else
    loclk_dly <= {loclk_dly[0], (clock_selector == CK_LOW) && !hiclk_dly[1] && !intclk_dly[1] };

always @(negedge hi_clk or posedge hw_reset)
  if (hw_reset) hiclk_dly <= 2'b00; else
    hiclk_dly <= {hiclk_dly[0], (clock_selector == CK_HIGH) && !loclk_dly[1] && !intclk_dly[1] };

always @(negedge int_clk or posedge hw_reset)
  if (hw_reset) intclk_dly <= 2'b11; else
    intclk_dly <= {intclk_dly[0], ((clock_selector != CK_LOW) && (clock_selector != CK_HIGH)) && !hiclk_dly[1] && !loclk_dly[1] };

  wire tclk=(lo_clk & loclk_dly[1]) | (hi_clk & hiclk_dly[1]) | (int_clk & intclk_dly[1]);
  global gbl1 (.in(tclk), .out(outclk));
des333
А тот, который Альтера предлашает, чем не годится? smile.gif
Код
module clock_mux (clk,clk_select,clk_out);
parameter num_clocks = 4;
input [num_clocks-1:0] clk;
input [num_clocks-1:0] clk_select; // one hot
output clk_out;
genvar i;
reg [num_clocks-1:0] ena_r0;
reg [num_clocks-1:0] ena_r1;
reg [num_clocks-1:0] ena_r2;
wire [num_clocks-1:0] qualified_sel;
// A look-up-table (LUT) can glitch when multiple inputs
// change simultaneously. Use the keep attribute to
// insert a hard logic cell buffer and prevent
// the unrelated clocks from appearing on the same LUT.
wire [num_clocks-1:0] gated_clks /* synthesis keep */;
initial begin
ena_r0 = 0;
ena_r1 = 0;
ena_r2 = 0;
end
generate
for (i=0; i<num_clocks; i=i+1)
begin : lp0
wire [num_clocks-1:0] tmp_mask;
assign tmp_mask = {num_clocks{1'b1}} ^ (1 << i);
assign qualified_sel[i] = clk_select[i] &
(~|(ena_r2 & tmp_mask));
always @(posedge clk[i]) begin
ena_r0[i] <= qualified_sel[i];
ena_r1[i] <= ena_r0[i];
end
always @(negedge clk[i]) begin
ena_r2[i] <= ena_r1[i];
end
assign gated_clks[i] = clk[i] & ena_r2[i];
end
endgenerate
// These will not exhibit simultaneous toggle by construction
assign clk_out = |gated_clks;
endmodule
des00
Цитата(SM @ Jan 18 2010, 11:06) *
Более правильный вариант вообще четвертый, до четырех клоков расширяется по аналогии smile.gif

спасибо, если я правильно понял в моем варианте нет асинхронных сбросов, как у вас и вы по сбросу ставите мультиплексор в определенное положение?


Цитата(des333 @ Jan 18 2010, 11:09) *
А тот, который Альтера предлашает, чем не годится? smile.gif

этот вариант эквивалентен приведеном коду %)

у меня ква для сыклона 3 сгенерировал
CODE

//synthesis_resources = clkctrl 1
//synopsys translate_off
`timescale 1 ps / 1 ps
//synopsys translate_on
module switch_altclkctrl_9nd
(
clkselect,
ena,
inclk,
outclk) ;
input [1:0] clkselect;
input ena;
input [3:0] inclk;
output outclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 [1:0] clkselect;
tri1 ena;
tri0 [3:0] inclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

wire wire_clkctrl1_outclk;
wire [1:0] clkselect_wire;
wire [3:0] inclk_wire;

cycloneiii_clkctrl clkctrl1
(
.clkselect(clkselect_wire),
.ena(ena),
.inclk(inclk_wire),
.outclk(wire_clkctrl1_outclk)
// synopsys translate_off
,
.devclrn(1'b1),
.devpor(1'b1)
// synopsys translate_on
);
defparam
clkctrl1.clock_type = "Global Clock",
clkctrl1.ena_register_mode = "falling edge",
clkctrl1.lpm_type = "cycloneiii_clkctrl";
assign
clkselect_wire = {clkselect},
inclk_wire = {inclk},
outclk = wire_clkctrl1_outclk;
endmodule //switch_altclkctrl_9nd
//VALID FILE


// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module switch (
clkselect,
inclk0x,
inclk1x,
inclk2x,
inclk3x,
outclk);

input [1:0] clkselect;
input inclk0x;
input inclk1x;
input inclk2x;
input inclk3x;
output outclk;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
tri0 [1:0] clkselect;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

wire sub_wire0;
wire sub_wire1 = 1'h1;
wire sub_wire6 = inclk3x;
wire sub_wire5 = inclk2x;
wire sub_wire4 = inclk0x;
wire outclk = sub_wire0;
wire sub_wire2 = inclk1x;
wire [3:0] sub_wire3 = {sub_wire6, sub_wire5, sub_wire2, sub_wire4};

switch_altclkctrl_9nd switch_altclkctrl_9nd_component (
.ena (sub_wire1),
.inclk (sub_wire3),
.clkselect (clkselect),
.outclk (sub_wire0));

endmodule

этот компонент требует подачи части клоков с PLL, о чем ква радостно сообщает
Цитата
Error: inclk[2] port of Clock Control Block "switch_altclkctrl_9nd:switch_altclkctrl_9nd_component|clkctrl1" is driven by inclk2x~input, but must be driven by a PLL clock output
Error: inclk[3] port of Clock Control Block "switch_altclkctrl_9nd:switch_altclkctrl_9nd_component|clkctrl1" is driven by inclk3x~input, but must be driven by a PLL clock output
SM
Цитата(des00 @ Jan 18 2010, 20:16) *
спасибо, если я правильно понял в моем варианте нет асинхронных сбросов, как у вас и вы по сбросу ставите мультиплексор в определенное положение?

Ну да, у меня он (асинхронный сброс) идет с ASIC-ового блока brownout детектора, чтобы гарантировать старт ядра от нужного генератора. А то можно ненароком и не завестись вообще, случайно по включению питания оказавшись на тактировании с выключенного кварцевого генератора....

Что касается альтерских вариантов - я просто не знал об их существовании вообще. И не разбирал. И лень smile.gif
des00
Цитата(SM @ Jan 18 2010, 11:32) *
Ну да, у меня он (асинхронный сброс) идет с ASIC-ового блока brownout детектора, чтобы гарантировать старт ядра от нужного генератора. А то можно ненароком и не завестись вообще, случайно по включению питания оказавшись на тактировании с выключенного кварцевого генератора....

Понял, спасибо. В моем случае таких вывертов нет, можно обойтись и без сброса, а select после загрузки ПЛИС будет стоять дефолтовский. Значит поставлю один мультиплексор 4в1.
dvladim
А почему бы не перевести все триггера на передний фронт.
Тогда смеситель будет выглядеть так:
Код
assign gated_clks[i] = clk[i] | ena_r2[i];

assign clk_out = &gated_clks;

и наверное, желательно, после каждого gated_clks поставить принудительно lcell.
SM
Цитата(dvladim @ Jan 19 2010, 23:10) *
А почему бы не перевести все триггера на передний фронт.

IMHO не суть важно, какой полярности логика и что на выходе, когда в процессе переключения нет ни одного клока.

Цитата(dvladim @ Jan 19 2010, 23:10) *
и наверное, желательно, после каждого gated_clks поставить принудительно lcell.

Лучше грамотно обконстрейнить недра через set_max_delay
des00
Цитата(dvladim @ Jan 19 2010, 14:10) *
А почему бы не перевести все триггера на передний фронт.

хмм, как я понял используется именно спадающий фронт для корректного выключения/включения клока. Если делать все на восходящем фронте, то возможно укорочение периода клока, связанное с Tco + задержкой выключающего триггера. Не глитч конечно, но тем не менее.


Цитата(SM @ Jan 19 2010, 14:19) *
Лучше грамотно обконстрейнить недра через set_max_delay

а разве констрейнов на клок не достаточно для данной схемы? интересуют именно асики, на форуме альтеры читал что ква старается в любом случае минимизировать длину трасс, поэтому большого смысла в задании таких задержек нет.
dvladim
Цитата(des00 @ Jan 20 2010, 06:42) *
хмм, как я понял используется именно спадающий фронт для корректного выключения/включения клока. Если делать все на восходящем фронте, то возможно укорочение периода клока, связанное с Tco + задержкой выключающего триггера. Не глитч конечно, но тем не менее.

Неее, задний фронт используется тогда когда клок с энейблом смешиваются по И, если мешать по ИЛИ нужно использовать передний фронт. В этих случаях tco триггера может быть от 0 до половины периода и это не будет влиять на выходной клок.

А что касается lcell мысль такая: например имеем переключатель 2-х клоков - (c0 & e0) | (c1 & e1) и все это попадает в ЛУТ. причем оба клока всегда молотят. Могут ли возникнуть глитчи или нет точно не знаю. Если разделить на разные луты, то при ЛУТ = (c0 & e0) глитчи точно не возникнут.
SM
Цитата(des00 @ Jan 20 2010, 06:42) *
а разве констрейнов на клок не достаточно для данной схемы?

нет конечно, недостаточно. Сам мультиплексор оказывается необконстрейненным из-за асинхронности клоков. Поэтому надо конкретно прописать максимально допустимые задержки, чтобы потом в STA проверить, выполняются ли они, и не сотворил ли плейсер-роутер всяких чудес, что типа как енейбл идет до мультиплексора дольше чем период клока smile.gif Т.е. сам клок гарантировано будет подан правильно, так как входы мультиплексора это ендпойнты дерева, а вот энейблы - вопрос отдельный.
des00
Цитата(dvladim @ Jan 20 2010, 12:03) *
А что касается lcell мысль такая: например имеем переключатель 2-х клоков - (c0 & e0) | (c1 & e1) и все это попадает в ЛУТ. причем оба клока всегда молотят. Могут ли возникнуть глитчи или нет точно не знаю. Если разделить на разные луты, то при ЛУТ = (c0 & e0) глитчи точно не возникнут.

хмм, но ведь мультиплексор сначала выключает оба клока и только потом включает один из них. По идее глитч возникнуть не может %)

Цитата(SM @ Jan 20 2010, 12:28) *
Т.е. сам клок гарантировано будет подан правильно, так как входы мультиплексора это ендпойнты дерева, а вот энейблы - вопрос отдельный.

Понял спасибо %)
SM
Цитата(des00 @ Jan 21 2010, 07:56) *
По идее глитч возникнуть не может %)

Это если роутер не сделает путь в три круга вокруг всего чипа smile.gif И сигнал о том, что клок выключили, не задержится на пару периодов клока.
des00
Цитата(SM @ Jan 21 2010, 01:20) *
Это если роутер не сделает путь в три круга вокруг всего чипа smile.gif И сигнал о том, что клок выключили, не задержится на пару периодов клока.

нда, общение только с фпга расхолаживает %) у ква роутер так точно делать не будет %)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.