SM 13 August 20, 2014 Posted August 20, 2014 · Report post А самый простой, надежный, и поддерживающий все нюансы протокола способ - соединить их "соплей" снаружи :) :) Наверняка и на одной половине шины, и на другой, есть резисторы, поэтому подсопливиться туда проблем быть не должно. Quote Share this post Link to post Share on other sites More sharing options...
egorman44 0 August 20, 2014 Posted August 20, 2014 · Report post :a14: Господа огромное спасибо всем ответившим. Сижу леплю. По мере возникновения вопросов буду их задавать . Quote Share this post Link to post Share on other sites More sharing options...
egorman44 0 August 20, 2014 Posted August 20, 2014 · Report post А самый простой, надежный, и поддерживающий все нюансы протокола способ - соединить их "соплей" снаружи :) :) Наверняка и на одной половине шины, и на другой, есть резисторы, поэтому подсопливиться туда проблем быть не должно. очень бы хотелось, но плата вне зоны досягаемости, боюсь еще даже не появилась на свет, и работать с ней придется по teamviewer'y Вообщем получилась следующая фиговина Quote Share this post Link to post Share on other sites More sharing options...
SM 13 August 20, 2014 Posted August 20, 2014 · Report post Ну выглядит как-то не очень корректно... Во первых, на вход контроллера должны идти как SDA1, так и SDA2. Чтобы определить, кто из них инициатор нуля на этой линии. У Вас же идет туда только SDA1. Во вторых, по идее, не должно быть прямого пути SDA1->SDA2 и SDA2->SDA1. На оба SDA должны идти только сигналы, разрешающие выдачу нуля на выходы, либо запрещающие выходы вообще (выход типа Open Drain). То есть на входе данных тристабильного буфера должен быть жесткий ноль (у Вас - данные с другого SDAx), ну а разрешением управлять от контроллера, тем самым эмулируя Open Drain. В третьих, для начала, если известно, где мастер, то SCL там не нужна вообще. Quote Share this post Link to post Share on other sites More sharing options...
10ff 0 August 20, 2014 Posted August 20, 2014 · Report post Может быть вопрос дурацкий, но почему нельзя сделать как на рисунке? Quote Share this post Link to post Share on other sites More sharing options...
SM 13 August 20, 2014 Posted August 20, 2014 · Report post Может быть вопрос дурацкий, но почему нельзя сделать как на рисунке? Эту схему заклинит навечно в нуле от первого же нуля на любом SDA по причине наличия 100% положительной обратной связи (в аналоговом смысле этого словосочетания). Quote Share this post Link to post Share on other sites More sharing options...
eugen_pcad_ru 0 August 21, 2014 Posted August 21, 2014 · Report post А самый простой, надежный, и поддерживающий все нюансы протокола способ - соединить их "соплей" снаружи :) :) Наверняка и на одной половине шины, и на другой, есть резисторы, поэтому подсопливиться туда проблем быть не должно. +1 Quote Share this post Link to post Share on other sites More sharing options...
egorman44 0 August 22, 2014 Posted August 22, 2014 · Report post Эту схему заклинит навечно в нуле от первого же нуля на любом SDA по причине наличия 100% положительной обратной связи (в аналоговом смысле этого словосочетания). и у меня почему-то что-то подобное получается. :laughing: always @(*) begin next = 'bx; SDA2_output_en = 1'b0; SDA1_output_en = 1'b0; case(state) IDLE: begin if ((SDA1_reg[2]) && (!SDA1_reg[1])) // если на SDA1 1->0 next = SDA2_OUT_EN; // делаем SDA2 выходом else if ((SDA2_reg[2]) && (!SDA2_reg[1])) // если на SDA2 1->0 next = SDA1_OUT_EN; // делаем SDA1 выходом else next = IDLE; end SDA2_OUT_EN: begin SDA2_output_en = 1'b1; if((!SDA1_reg[2]) && (SDA1_reg[1])) // ждем переход на SDA1 0->1 next = IDLE; // чтобы отпустить SDA2 else next = SDA2_OUT_EN; end SDA1_OUT_EN: begin SDA1_output_en = 1'b1; if ((!SDA2_reg[2]) && (SDA2_reg[1])) // ждем переход на SDA2 0->1 next = IDLE; // чтобы отпустить SDA1 else next = SDA1_OUT_EN; end endcase end // drive output signals assign SDA1 = (SDA1_output_en) ? (1'b0) : (1'bz); assign SDA2 = (SDA2_output_en) ? (1'b0) : (1'bz); endmodule в симуляторе работает такое ,а вот в железку не встает . SDA2 всегда 0 . Quote Share this post Link to post Share on other sites More sharing options...
des00 26 August 22, 2014 Posted August 22, 2014 · Report post в симуляторе работает такое ,а вот в железку не встает . SDA2 всегда 0 . И не будет работать. Вам же сказали можно на достаточно высокой частоте мониторить оба входа-выхода, Quote Share this post Link to post Share on other sites More sharing options...
egorman44 0 August 22, 2014 Posted August 22, 2014 · Report post И не будет работать. Вам же сказали ЭЭэээ , извиняюсь конечно, что не выложил первую часть кода, но я подумал , что она сама собой подразумевающаяся и захламлсять пространство, ну очень уж не хотелось вот так , пойдет ? ////////////////////////////////////////////////////////////////////////////////// module I2C_bypassSM( input rst_n, input sys_clk, input SCL_IN, inout SDA1, inout SDA2, output SCL_OUT ); // ---------------------------- // Shifting SDA1 and SDA2 into // a sync circuit // ---------------------------- reg [2:0] SDA1_reg; reg [2:0] SDA2_reg; always @(posedge sys_clk) begin if(rst) begin SDA1_reg <= 0; SDA2_reg <= 0; end else begin SDA1_reg <= {SDA1_reg[1:0],SDA1}; SDA2_reg <= {SDA2_reg[1:0],SDA2}; end end //----------------------------- // FSM for driving tri-state // outputs //----------------------------- parameter IDLE = 2'b00, SDA1_OUT_EN = 2'b01, SDA2_OUT_EN = 2'b10; reg [1:0] state, next; reg SDA2_output_en; // a drive signal for tri-state buffer reg SDA1_output_en; // a drive signal for tri-state buffer always @(posedge sys_clk, posedge rst_n) begin if (rst_n) state <= IDLE; else state <= next; end always @(*) begin next = 'bx; SDA2_output_en = 1'b0; SDA1_output_en = 1'b0; case(state) IDLE: begin if ((SDA1_reg[2]) && (!SDA1_reg[1])) // если на SDA1 1->0 next = SDA2_OUT_EN; // делаем SDA2 выходом else if ((SDA2_reg[2]) && (!SDA2_reg[1])) // если на SDA2 1->0 next = SDA1_OUT_EN; // делаем SDA1 выходом else next = IDLE; end SDA2_OUT_EN: begin SDA2_output_en = 1'b1; if((!SDA1_reg[2]) && (SDA1_reg[1])) // ждем переход на SDA1 0->1 next = IDLE; // чтобы отпустить SDA2 else next = SDA2_OUT_EN; end SDA1_OUT_EN: begin SDA1_output_en = 1'b1; if ((!SDA2_reg[2]) && (SDA2_reg[1])) // ждем переход на SDA2 0->1 next = IDLE; // чтобы отпустить SDA1 else next = SDA1_OUT_EN; end endcase end // drive output signals assign SDA1 = (SDA1_output_en) ? (1'b0) : (1'bz); assign SDA2 = (SDA2_output_en) ? (1'b0) : (1'bz); endmodule Quote Share this post Link to post Share on other sites More sharing options...
SM 13 August 22, 2014 Posted August 22, 2014 · Report post Что-то у Вас там слишком много букв :) вот как-то так... (писал прямо сюда, поэтому без гарантий, что не наглючил) module SDA_bypass (sda1_in, sda2_in, sda1_out, sda2_out, clk); input sda1_in, sda2_in, clk; output sda1_out, sda2_out; reg [2:0] sda1_reg, sda2_reg; reg dir; /* receivers. 1'st stage to avoid metastability, 2'nd - receiver FF, 3'rd - for edge detect*/ always @(posedge clk) sda1_reg <= {sda1_reg[1:0], sda1_in}; always @(posedge clk) sda2_reg <= {sda2_reg[1:0], sda2_in}; /* direction control */ always @(posedge clk) if (sda1_reg[1] && !sda2_reg[1] && sda2_reg[2]) dir <= 1'b1; // sda2 -> sda1 else if (!sda1_reg[1] && sda1_reg[2] && sda2_reg[1]) dir <= 1'b0; // sda1 -> sda2 /* log. zero output enable signals */ assign sda2_out = !dir & !sda1_reg[1]; assign sda1_out = dir & !sda2_reg[1]; endmodule UPD: поправил чуток по мелочи. Quote Share this post Link to post Share on other sites More sharing options...
egorman44 0 August 22, 2014 Posted August 22, 2014 · Report post Что-то у Вас там слишком много букв :) это я просто FSM'ки тренируюсь писать Quote Share this post Link to post Share on other sites More sharing options...
xvr 12 September 1, 2014 Posted September 1, 2014 · Report post А что нибудь типа P82B96 снаружи поставить не судьба? Quote Share this post Link to post Share on other sites More sharing options...