greyrus 0 1 марта, 2012 Опубликовано 1 марта, 2012 · Жалоба Добрый день! Есть такая задача, подключить к ПЛИС Xilinx XC3S50AN несколько датчиков температуры DS18b20 и считывать с них значение температуры. С плис начал работать совсем недавно. Подскажите в какую сторону копать, может у кого есть опыт таких разработок. Буду благодарен за любую помощь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 1 марта, 2012 Опубликовано 1 марта, 2012 · Жалоба ...Подскажите в какую сторону копать... Например в эту. (я так понимаю в гугуле завелись жёсткие админы которые банят всех начинающих...) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexadmin 0 5 марта, 2012 Опубликовано 5 марта, 2012 · Жалоба Добрый день! Есть такая задача, подключить к ПЛИС Xilinx XC3S50AN несколько датчиков температуры DS18b20 и считывать с них значение температуры. С плис начал работать совсем недавно. Подскажите в какую сторону копать, может у кого есть опыт таких разработок. Буду благодарен за любую помощь. У Xilinx был готовый проект для чтения по 1-wire. Представлял он жуткий говнокод, но у него было неиспоримый плюс: он работал. Поищите на их сайте. PS Первая же ссылка в гугле по запросу "xilinx 1-wire" ведет на XAPP198 с подробным описанием. Где-то рядом есть и готовый проект Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BSACPLD 15 5 марта, 2012 Опубликовано 5 марта, 2012 · Жалоба Делал на SV, но переписать на обычный Verilog не очень сложно. `timescale 1 ns / 1 ps module DS18X20_CTRL #( parameter [8:0] CLKDIV = 9'd80 ) ( input clk, input read, output reg [15:0] temp, output error, inout IO ) ; localparam start = 3'd0, reset_1wire = 3'd1, check_termometer = 3'd2, write_cmd = 3'd3, wait_convert = 3'd4, read_scratchpad = 3'd5 ; reg [2:0] state = start ; reg [2:0] next_state = start ; reg [8:0] divider = 0 ; wire divider_cout ; reg divider_cout_clk = 1'b0 ; reg [8:0] timer = 0 ; wire timer_cout ; reg [8:0] toggle_cmp = 0 ; wire toggle ; wire read_1wire ; reg [15:0] shift = 0 ; reg [15:0] buffer = 0 ; reg error_n = 1'b0 ; reg [6:0] bit_cnt = 0 ; wire bit_cnt_cout ; reg out_reg_n = 1'b0 ; reg [1:0] in_reg = 0 ; reg [7:0] CRC = 0 ; wire XOR0 ; initial begin temp <= 0 ; end assign error = ~error_n ; assign IO = (out_reg_n)? 1'b0:1'bZ ; assign divider_cout = (divider == 0) ; assign timer_cout = (timer == 0) ; assign toggle = (timer == toggle_cmp) ; assign read_1wire = (timer == 9'd60) ; assign bit_cnt_cout = (bit_cnt == 0) ; assign XOR0 = CRC[0] ^ in_reg[1] ; always_ff @(posedge clk) begin if (read) temp <= buffer ; end always_ff @(posedge clk) begin in_reg <= (in_reg << 1) | IO ; end always_ff @(posedge clk) begin if (divider_cout) divider <= CLKDIV ; else divider <= divider - 1'b1 ; divider_cout_clk <= divider_cout ; end always_ff @(posedge clk) begin if (divider_cout_clk) begin case (state) start: if (timer_cout) begin state <= reset_1wire ; next_state <= wait_convert ; timer <= 9'd500 ; shift <= 16'h44CC ; bit_cnt <= 7'd16 ; out_reg_n <= 1'b1 ; end else begin timer <= timer - 1'b1 ; end reset_1wire: if (timer_cout) begin state <= check_termometer ; timer <= 9'd500 ; toggle_cmp <= 9'd432 ; out_reg_n <= 1'b0 ; end else begin timer <= timer - 1'b1 ; end check_termometer: if (timer_cout) begin state <= write_cmd ; end else begin timer <= timer - 1'b1 ; if (toggle & in_reg[1]) begin state <= start ; error_n <= 1'b0 ; end end write_cmd: begin if (timer_cout) begin if (bit_cnt_cout) begin state <= next_state ; end else begin timer <= 9'd70 ; if (shift[0]) toggle_cmp <= 9'd65 ; else toggle_cmp <= 9'd5 ; shift[15:0] <= {in_reg[1], shift[15:1]} ; bit_cnt <= bit_cnt - 1'b1 ; out_reg_n <= 1'b1 ; end end else begin timer <= timer - 1'b1 ; if (toggle) out_reg_n <= 1'b0 ; end end wait_convert: begin if (timer_cout) begin if (next_state == read_scratchpad) begin state <= reset_1wire ; timer <= 9'd500 ; shift <= 16'hBECC ; bit_cnt <= 7'd16 ; end else begin timer <= 9'd70 ; toggle_cmp <= 9'd65 ; end out_reg_n <= 1'b1 ; end else begin timer <= timer - 1'b1 ; if (read_1wire & in_reg[1]) next_state <= read_scratchpad ; if (toggle) out_reg_n <= 1'b0 ; end end read_scratchpad: begin if (timer_cout) begin if (bit_cnt_cout & (next_state == start)) begin state <= start ; if (CRC != 0) begin error_n <= 1'b0 ; end else begin error_n <= 1'b1 ; buffer <= shift ; end end else begin timer <= 9'd70 ; if (next_state != start) begin bit_cnt <= 7'd71 ; CRC <= 0 ; end else begin bit_cnt <= bit_cnt - 1'b1 ; end out_reg_n <= 1'b1 ; end next_state <= start ; end else begin timer <= timer - 1'b1 ; if (read_1wire) begin if (bit_cnt > 7'd55) shift[15:0] <= {in_reg[1], shift[15:1]} ; CRC <= {XOR0, CRC[7:5], CRC[4] ^ XOR0, CRC[3] ^ XOR0, CRC[2:1]} ; end if (toggle) out_reg_n <= 1'b0 ; end end default: state <= start ; endcase end end endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IEC 1 5 марта, 2012 Опубликовано 5 марта, 2012 · Жалоба Посмотрите http://www.ourdev.cn/bbs/bbs_content.jsp?b...amp;bbs_id=1029 Может поможет для начала. Удачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ovs_pavel 0 6 марта, 2012 Опубликовано 6 марта, 2012 · Жалоба Если поможет, такая реализация: `timescale 1ns / 1ps module iButton( // --------------- Сигналы сброса и синхронизации. --------------- // input LRESETn, // Асинхронный сброс (формируется после того, как уровни напряжения питания моста будут в допуске). input wFtakt, // Тактовая частота 33 МГц. // --------------- Внутренние сигналы. --------------- // input [7:0] D_CPU_iBut, // Данные для выдачи по интерфейсу 1-Wire. input [1:0] CMD_In, // Код операции. input [3:0] Add_In, // Адрес регистра данных/команд со стороны адресного простанства процессора (Add_In = 4'b0101). input WE, // Сигнал записи в регистр данных/команд (запускает автомат состояний). input OE, // Сигнал подтверждения ("1") операции записи. input CS, // Сигнал выбора кристалла ("0"). output [7:0] D_iBut_CPU, // Данные, принятые по интерфейсу 1-Wire. output [1:0] CMD_Out, // Команда, записанная в приемный регистр команд. output iBut_Busy, // Линия занята (сигнал логической "1" - наличие обмена данными). output iBut_Pres, // Устройство присутствует на шине (сигнал логической "1" - устройство на шине). // --------------- Интерфейс 1-Wire. --------------- // input iButIn, output iButOut ); // --------------- Регистр команд. --------------- // reg [1:0] RgCom; always @(posedge WE or negedge LRESETn) begin if (~LRESETn) RgCom <= 2'd0; else if ((Add_In == 4'b1000) && OE && ~CS) RgCom <= CMD_In; end assign CMD_Out = RgCom; wire w_Res_iBut = (RgCom == 2'b00); // Инициирована диаграмма сброса с последующим определением устройства на шине. wire w_Wr_iBut = (RgCom == 2'b01); // Инициирована диаграмма записи данных в устройство. // --------------- Регистр наличия (уровень логической "1") устройства i-Button на шине. --------------- // reg Rg_iB_PRS; // Регистр наличия устройства i-Button на шине. reg Ena_Rg_iB_PRS; // Установка в "1" регистра наличия устройства i-Button на шине. reg Clr_Rg_iB_PRS; // Сброс в "0" регистра наличия устройства i-Button на шине. always @(posedge wFtakt or posedge Clr_Rg_iB_PRS) begin if (Clr_Rg_iB_PRS) Rg_iB_PRS <= 1'b0; else if (Ena_Rg_iB_PRS) Rg_iB_PRS <= 1'b1; end assign iBut_Pres = Rg_iB_PRS; // --------------- Регистр занятости (уровень логической "1") устройства i-Button на шине. --------------- // reg Rg_iB_BSY; // Регистр занятости устройства i-Button на шине. reg Clr_Rg_iB_BSY; // Сброс в "0" регистра занятости устройства i-Button на шине. always @(posedge WE or posedge Clr_Rg_iB_BSY) begin if (Clr_Rg_iB_BSY) Rg_iB_BSY <= 1'b0; else if ((Add_In == 4'b1000) && OE && ~CS) Rg_iB_BSY <= 1'b1; end assign iBut_Busy = Rg_iB_BSY; // --------------- Строб запуска автомата состояний. --------------- // /* Импульс формируется из строба занятости устройства путем привязки к основной тактовой частоте и задержки на соответствующее кол-во тактов. Этот же импульс, записывает принятые данные в сдвиговый регистр выдачи данных. */ reg Rg_iB_BSY_Z1; // Задержка строба занятости на один такт. reg Rg_iB_BSY_Z2; // Задержка строба занятости на два такта. always @(posedge wFtakt or negedge LRESETn) begin if (~LRESETn) begin Rg_iB_BSY_Z1 <= 1'b0; Rg_iB_BSY_Z2 <= 1'b0; end else begin Rg_iB_BSY_Z1 <= Rg_iB_BSY; Rg_iB_BSY_Z2 <= Rg_iB_BSY_Z1; end end wire Rg_Start_SM = Rg_iB_BSY_Z1 && ~Rg_iB_BSY_Z2; // --------------- Приемный регистр команд/данных шины iButton. --------------- // reg [7:0] Rec_Rg_CD; always @(posedge WE or negedge LRESETn) begin if (~LRESETn) Rec_Rg_CD <= 8'd0; else if ((Add_In == 4'b1000) && OE && ~CS) Rec_Rg_CD <= D_CPU_iBut; end // --------------- Сдвиговый регистр выдачи команд/данных шины iButton. --------------- // /* Данные выдаются на линию в следующей последовательности: D[0], D[1], D[2]...D[6], D[7]. */ reg [7:0] Rg_CD; // Сдвиговый регистр выдачи команд/данных шины iButton. reg Ena_Rg_CD; // Разрешение сдвига данных регистра 'Rg_CD'. always @(posedge wFtakt or negedge LRESETn) begin if (~LRESETn) Rg_CD <= 8'd0; else if (Rg_Start_SM) Rg_CD <= Rec_Rg_CD; else if (Ena_Rg_CD) begin Rg_CD[6:0] <= Rg_CD[7:1]; Rg_CD[0] <= Rg_CD[1]; end end // --------------- Мультиплексор управления выдачей на линию данных iButton либо "1", либо "0", либо разряда данных. --------------- // reg [1:0] Upr_MUX; reg Rg_iB_Out; // Регистр выдачи данных. always @ (posedge wFtakt) begin case (Upr_MUX) 2'd0 : Rg_iB_Out <= 1'b1; 2'd1 : Rg_iB_Out <= 1'b0; 2'd2 : Rg_iB_Out <= Rg_CD[0]; default : Rg_iB_Out <= 1'b1; endcase end assign iButOut = Rg_iB_Out; // --------------- Cчетчик длительности импульса сброса в режиме инициализации. --------------- // /* Разрядность счетчика 2^14 = 16384. Тактовая частота счетчика 32 МГц, следовательно период 31,25 нсек. */ reg [13:0] CntRes; // Cчетчик длительности импульса сброса в режиме инициализации. reg EnaCntRes; // Разрешение счета счетчика 'CntRes'. reg ClrCntRes; // Сигнал сброса счетчика 'CntRes'. always @(posedge wFtakt or negedge ClrCntRes) begin if (~ClrCntRes) CntRes <= 14'd0; else if (EnaCntRes) CntRes <= CntRes + 1'b1; end wire w_512us = (CntRes == 14'h3FFF); // Значение счетчика 'CntRes' равно 16384 (512 мкс). wire w_100us = (CntRes == 14'h0C80); // Значение счетчика 'CntRes' равно 3200 (100 мкс). // --------------- Привязка цепей 'w_512us' и 'w_100us' к тактовой частоте. --------------- // reg Rg_w_512us; reg Rg_w_100us; always @(posedge wFtakt or negedge LRESETn) begin if (~LRESETn) begin Rg_w_512us <= 1'b0; Rg_w_100us <= 1'b0; end else begin Rg_w_512us <= w_512us; Rg_w_100us <= w_100us; end end // --------------- Cчетчик формирования диаграммы записи/чтения данных. --------------- // /* Разрядность счетчика 2^11 = 2048. Рабочие интервалы (счетчик 11-ти разрядный): 48 * 31,25 нсек = 1,5 мксек. 480 * 31,25 нсек = 15 мксек. 2000 * 31,25 нсек = 62,5 мксек. 2048 * 31,25 нсек = 64 мксек. */ reg [10:0] CntData; // Cчетчик формирования диаграммы записи/чтения данных. reg EnaCntData; // Разрешение счета счетчика 'CntData'. reg ClrCntData; // Сигнал сброса счетчика 'CntData'. always @(posedge wFtakt or negedge ClrCntData) begin if (~ClrCntData) CntData <= 11'd0; else if (EnaCntData) CntData <= CntData + 1'b1; end wire w_1_5us = (CntData == 11'h2F); // Значение счетчика 'CntData' равно 48 (1,5 мкс). wire w_15us = (CntData == 11'h1DF); // Значение счетчика 'CntData' равно 480 (15 мкс). wire w_62_5us = (CntData == 11'h7CF); // Значение счетчика 'CntData' равно 2000 (62,5 мкс). wire w_64us = (CntData == 11'h7FF); // Значение счетчика 'CntData' равно 2048 (64 мкс). // --------------- Привязка цепей 'w_1_5us', 'w_15us', 'w_62_5us', 'w_64us' к тактовой частоте. --------------- // reg Rg_w_1_5us; reg Rg_w_15us; reg Rg_w_62_5us; reg Rg_w_64us; always @(posedge wFtakt or negedge LRESETn) begin if (~LRESETn) begin Rg_w_1_5us <= 1'b0; Rg_w_15us <= 1'b0; Rg_w_62_5us <= 1'b0; Rg_w_64us <= 1'b0; end else begin Rg_w_1_5us <= w_1_5us; Rg_w_15us <= w_15us; Rg_w_62_5us <= w_62_5us; Rg_w_64us <= w_64us; end end // --------------- Cчетчик числа принятых/переданных бит в режиме записи/чтения команд/данных. --------------- // reg [2:0] CntDatR; // Cчетчик числа принятых/переданных бит в режиме записи/чтения команд/данных. reg ClrCntDatR; // Сигнал сброса счетчика 'CntDatR'. always @(posedge wFtakt or negedge ClrCntDatR) begin if (~ClrCntDatR) CntDatR <= 3'd0; else if (Ena_Rg_CD) CntDatR <= CntDatR + 1'b1; end // --------------- Привязка входной линии данных к тактовой частоте. --------------- // reg Rg_iB_In; always @(posedge wFtakt or negedge LRESETn) begin if (~LRESETn) Rg_iB_In <= 1'b0; else Rg_iB_In <= iButIn; end // --------------- Приемный регистр данных с шины i-Button. --------------- // /* Данные принимаются в следующей последовательности: D[0], D[1], D[2], D[3]...D[6], D[7]. */ reg [7:0] RgRdShift; // Приемный регистр данных с шины i-Button. reg EnaRdShift; // Сигнал разрешения записи в сдвиговый регистр в цикле чтения данных. always @(posedge wFtakt or negedge LRESETn) begin if (~LRESETn) RgRdShift <= 8'd0; else if (EnaRdShift) begin RgRdShift[6:0] <= RgRdShift[7:1]; RgRdShift[7] <= Rg_iB_In; end end assign D_iBut_CPU = RgRdShift; // --------------- Объявление автомата состояний. --------------- // reg [9:0] State; parameter [9:0] Idle = 10'b0000000001, Wait_Zero = 10'b0000000010, Wait_One = 10'b0000000100, Wait_One2 = 10'b0000001000, CS_Low = 10'b0000010000, CS_TransD = 10'b0000100000, CS_RecD = 10'b0001000000, Wait_Exch = 10'b0010000000, End_Trans = 10'b0100000000, Back_Off = 10'b1000000000; // --------------- Автомат состояний Миля с синхронными выходами. --------------- // always @ (posedge wFtakt or negedge LRESETn) begin if (!LRESETn) begin State <= Idle; Ena_Rg_iB_PRS <= 1'b0; // Установка в "1" регистра наличия устройства i-Button на шине. Clr_Rg_iB_PRS <= 1'b0; // Сброс в "0" регистра наличия устройства i-Button на шине. Clr_Rg_iB_BSY <= 1'b0; // Сброс в "0" регистра занятости устройства i-Button на шине. EnaCntRes <= 1'b0; // Разрешение счета счетчика 'CntRes'. ClrCntRes <= 1'b0; // Сигнал сброса счетчика 'CntRes'. Upr_MUX <= 2'd0; // Мультиплексор управления выдачей на линию данных. Ena_Rg_CD <= 1'b0; // Разрешение сдвига данных регистра 'Rg_CD'. EnaCntData <= 1'b0; // Разрешение счета счетчика 'CntData'. ClrCntData <= 1'b0; // Сигнал сброса счетчика 'CntData'. ClrCntDatR <= 1'b0; // Сигнал сброса счетчика 'CntDatR'. EnaRdShift <= 1'b0; // Сигнал разрешения записи в сдвиговый регистр в цикле чтения данных. end else begin case (State) Idle: // Ожидание импульса запуска автомата состояний. begin if (Rg_Start_SM) begin Upr_MUX <= 2'd1; // На линию данных выдаем логический "0". if (w_Res_iBut) // Команда сброса с последующей инициализацией устройства на шине. begin State <= Wait_Zero; EnaCntRes <= 1'b1; ClrCntRes <= 1'b1; end else begin State <= CS_Low; EnaCntData <= 1'b1; ClrCntData <= 1'b1; ClrCntDatR <= 1'b1; end end else begin State <= Idle; end end Wait_Zero: begin if (Rg_w_512us) begin State <= Wait_One; Upr_MUX <= 2'd0; // На линию данных выдаем логическую "1". end else State <= Wait_Zero; end Wait_One: begin if (Rg_w_100us) begin if (Rg_iB_In) // На шине нет устройств. begin State <= End_Trans; Clr_Rg_iB_PRS <= 1'b1; end else begin State <= Wait_One2; // На шине есть устройства. Ena_Rg_iB_PRS <= 1'b1; end end else State <= Wait_One; end Wait_One2: begin Ena_Rg_iB_PRS <= 1'b0; if (Rg_w_512us) State <= End_Trans; else State <= Wait_One2; end CS_Low: begin Ena_Rg_CD <= 1'b0; if (Rg_w_1_5us) begin if (w_Wr_iBut) // Команда записи данных. begin State <= CS_TransD; Upr_MUX <= 2'd2; end else begin State <= CS_RecD; Upr_MUX <= 2'd0; end end else State <= CS_Low; end CS_TransD: begin if (Rg_w_62_5us) begin State <= Wait_Exch; Upr_MUX <= 2'd0; end else State <= CS_TransD; end CS_RecD: begin if (Rg_w_15us) begin State <= Wait_Exch; EnaRdShift <= 1'b1; end else State <= CS_RecD; end Wait_Exch: begin EnaRdShift <= 1'b0; if (Rg_w_64us) begin if (CntDatR == 3'd7) State <= End_Trans; else begin State <= CS_Low; Upr_MUX <= 2'd1; Ena_Rg_CD <= 1'b1; end end else State <= Wait_Exch; end End_Trans: begin State <= Back_Off; Clr_Rg_iB_PRS <= 1'b0; EnaCntRes <= 1'b0; ClrCntRes <= 1'b0; Clr_Rg_iB_BSY <= 1'b1; Upr_MUX <= 2'd0; EnaCntData <= 1'b0; ClrCntData <= 1'b0; ClrCntDatR <= 1'b0; end Back_Off: begin State <= Idle; Clr_Rg_iB_BSY <= 1'b0; end default: begin State <= Idle; Ena_Rg_iB_PRS <= 1'b0; Clr_Rg_iB_PRS <= 1'b0; Clr_Rg_iB_BSY <= 1'b0; EnaCntRes <= 1'b0; ClrCntRes <= 1'b0; Upr_MUX <= 2'd0; Ena_Rg_CD <= 1'b0; EnaCntData <= 1'b0; ClrCntData <= 1'b0; ClrCntDatR <= 1'b0; EnaRdShift <= 1'b0; end endcase end end endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shivers 0 6 марта, 2012 Опубликовано 6 марта, 2012 · Жалоба У Далласа (который 1-wire и придумал, собсно) есть свободнораспостраняемая корка 1-wire master с тестбенчем и документацией, написанная на vhdl и верилоге. Но суть в том, что этим мастером надо управлять, и если делать автомат того же автодетекта/поиска устройств на шине, то алгоритм реализованный на автомате получится просто чудовищный. Т.е., вам понадобится еще модель mcu для запихывания внутрь, и память для программы, чтобы все 1-wire эвенты обрабатывать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться