Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: uart verilog
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
sergey sva
Нужен uart с двумя сигналами rx tx , понимаю что не сложно сделать, может есть готовый? дайте ссылочку пожалуйста.
aT-DeviLru
Может быть подойдёт Verilog UART с opencores? ссылка - http://opencores.org/project,osdvu, для скачивания без регистрации можно перейти по ссылке "SVN: Browse" и перейти в папку trunk.
count_enable
На opencores.org их как грязи, если надо стандартный то Xilinx IPcore а для студента то здесь всё разжевано http://we.easyelectronics.ru/plis/ocheredn...ke-verilog.html .
filo
как передавать по uart 18битные данные? Я так понимаю нужен какой-то буфер, который будет принимать три 8битных слова с uart и выдавать на выход по 18бит?
Swup
Я как-то использовал модули отсюда:
http://www.fpga4fun.com/SerialInterface.html
Вот еще ссылка прямая: http://www.fpga4fun.com/files/async.zip
Заработало с пол тычка.



А насчет второго: ну да, передавать 3 слова, еще даже по 2 бита на слово лишних останется, можно вставить флаг какое это слово, проверку ну или уплотнить данные.
filo
Цитата(Swup @ Oct 23 2013, 08:20) *
Я как-то использовал модули отсюда:
http://www.fpga4fun.com/SerialInterface.html
Вот еще ссылка прямая: http://www.fpga4fun.com/files/async.zip
Заработало с пол тычка.



А насчет второго: ну да, передавать 3 слова, еще даже по 2 бита на слово лишних останется, можно вставить флаг какое это слово, проверку ну или уплотнить данные.

а есть какие-нибудь примеры подобных решений? или как это вообще называется? для поиска
count_enable
Сначала определитесь, хотите ли уарт, по которому будут ходить 18-битные данные, или просто последовательный интерфейс с 18-битным словом. В первом случае есть совместимость с любым уартом, данные жестко 8-битные со старт-стоп битами. Самый простой способ(но не самый эффективный): В каждом переданном байте первых 2 бита заголовок, который может быть 1,2 или 3. Остальные 6 бит данные.
Приёмник вынимает байт из буфера, заголовок идёт на мультиплексер, который запихивает 6 бит данных в начало, середину или конец длинного регистра. При каждом получении 3-ей части выставляем строб "Data ready".
Если же нужен просто последовательный интерфейс с 18-битным словом то модифицируем вышеприведенный код уарта так, чтобы отправлял 18-битные посылки вместо 8-битных. Несовместим с другими стандартами, но самый эффективный по скорости передачи и простоте интерфейса.
iosifk
Цитата(count_enable @ Oct 23 2013, 14:00) *
Если же нужен просто последовательный интерфейс с 18-битным словом то модифицируем вышеприведенный код уарта так, чтобы отправлял 18-битные посылки вместо 8-битных. Несовместим с другими стандартами, но самый эффективный по скорости передачи и простоте интерфейса.


Но при этом надо делать точное согласование по частоте. А стандартный СОМ может этого не понять...
Вообще лучше не изобретать кривые протоколы, когда есть Wake...
filo
Цитата(count_enable @ Oct 23 2013, 13:00) *
Сначала определитесь, хотите ли уарт, по которому будут ходить 18-битные данные, или просто последовательный интерфейс с 18-битным словом. В первом случае есть совместимость с любым уартом, данные жестко 8-битные со старт-стоп битами. Самый простой способ(но не самый эффективный): В каждом переданном байте первых 2 бита заголовок, который может быть 1,2 или 3. Остальные 6 бит данные.
Приёмник вынимает байт из буфера, заголовок идёт на мультиплексер, который запихивает 6 бит данных в начало, середину или конец длинного регистра. При каждом получении 3-ей части выставляем строб "Data ready".
Если же нужен просто последовательный интерфейс с 18-битным словом то модифицируем вышеприведенный код уарта так, чтобы отправлял 18-битные посылки вместо 8-битных. Несовместим с другими стандартами, но самый эффективный по скорости передачи и простоте интерфейса.

спасибо за ответ.
вообще планировалось использовать стандартный RS-232.
sergey sva
Спасибо и правда сразу заработало sm.gif
Нужен генератор црц 16 который в модбус рту используется, набрел на такой сайт он позволяет генерировать код, но как написано не очень нравиться, может есть более оптимальные, желательно что бы не много занимал ресурсов.
Andrew Su
Добрый день.
Посмотрите, может понравится.
Удачи.
sergey sva
Столкнулся с проблемой, никак не разберусь почему CRC код не совпадает. Взял пример сгенерированный http://outputlogic.com/ пробовал с разными полиномами 1+x^2+x^15+x^16; и 1+x^13+x^15+x^16;
Получается не такой результат какой должен быть.
Думал что ошибся в направлении прохода сделал все сигналы 00,00,00,00,00,00,00,00. Подумал что ошибся с количеством, вывел переменную countbytes, все правильно в ней 8.
CRC Должно получиться при проходе по шине из 8 байт с значением 00 = 0x0B40. А получается 0x02d0

Код
// Copyright (C) 2009 OutputLogic.com
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED    
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
// CRC module for data[7:0] ,   crc[15:0]=1+x^2+x^15+x^16;
//-----------------------------------------------------------------------------

module CRC( data_in, crc_en, crc_out,rst, clk, countbytes);
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
input [7:0] data_in;
input crc_en,rst, clk;
output [15:0] crc_out;
output[7:0] countbytes;
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
  reg [15:0] lfsr_q,lfsr_c;
  reg [7:0] countbytes_reg;
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
  assign crc_out = lfsr_q;
  assign countbytes = countbytes_reg;
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//

  assign crc_out = lfsr_q;

  always @(posedge clk, posedge rst) begin
    if(rst) begin
      lfsr_q = {16{1'b1}};
        countbytes_reg = 0;
    end
    else begin
    
        if(crc_en)
        begin        
            lfsr_c[0] = lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[14] ^ lfsr_q[15] ^ data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[7];
            lfsr_c[1] = lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[14] ^ lfsr_q[15] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[7];
            lfsr_c[2] = lfsr_q[8] ^ lfsr_q[9] ^ data_in[0] ^ data_in[1];
            lfsr_c[3] = lfsr_q[9] ^ lfsr_q[10] ^ data_in[1] ^ data_in[2];
            lfsr_c[4] = lfsr_q[10] ^ lfsr_q[11] ^ data_in[2] ^ data_in[3];
            lfsr_c[5] = lfsr_q[11] ^ lfsr_q[12] ^ data_in[3] ^ data_in[4];
            lfsr_c[6] = lfsr_q[12] ^ lfsr_q[13] ^ data_in[4] ^ data_in[5];
            lfsr_c[7] = lfsr_q[13] ^ lfsr_q[14] ^ data_in[5] ^ data_in[6];
            lfsr_c[8] = lfsr_q[0] ^ lfsr_q[14] ^ lfsr_q[15] ^ data_in[6] ^ data_in[7];
            lfsr_c[9] = lfsr_q[1] ^ lfsr_q[15] ^ data_in[7];
            lfsr_c[10] = lfsr_q[2];
            lfsr_c[11] = lfsr_q[3];
            lfsr_c[12] = lfsr_q[4];
            lfsr_c[13] = lfsr_q[5];
            lfsr_c[14] = lfsr_q[6];
            lfsr_c[15] = lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[14] ^ lfsr_q[15] ^ data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[6] ^ data_in[7];

            countbytes_reg = countbytes_reg +1;    
            lfsr_q  = lfsr_c;
        end
        else begin
        
            lfsr_q  = lfsr_q;
        end    
            
      
    end
  end // always



endmodule // crc
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
Zig
Цитата(sergey sva @ Oct 31 2013, 14:16) *
CRC Должно получиться при проходе по шине из 8 байт с значением 00 = 0x0B40. А получается 0x02d0

Код не смотрел, заметил, что если прочитать 0x0B40 задом на перед, то получается 0x02D0...
sergey sva
Сейчас проверю может в направлениях сигналов ошибся. Еще такой вопрос уарт должен принимать пакет из 64 байт как правильнее отследить конец начала пакета? Думаю сделать так устройство которое посылает пакет помещает в 0 байт символ $ и передает весь пакет в плис(64 байта).
Плис получает сигнал от модуля уарта, о том что пришел байт. каждый раз как приходит байт обнуляется счетчик, как только какое то время байты не поступают счетчик переполняется, проверяется 0 байт если там есть "$" , устанавливается сигнал пакет получен. У модуля уарт есть еще сигнал is_receive можно еще по нему отслеживать конец. Как правильнее реализовать такое может есть примеры. или просто на словах.
sergey sva
Пробовал реверс бит результат не совпадает (. С разными полиномами пробовал a001 8005.
Проверяю значения 0x24 0x08 0x00 0x00 0x00 0x00 CRC должно получиться 0x3EE7 а у меня 0x24d6, где ошибка ума нет. проверял на калькуляторе http://www.lammertbies.nl/comm/info/crc-calculation.html подскажите что нибудь?
Код
//-----------------------------------------------------------------------------
// Copyright (C) 2009 OutputLogic.com
// This source file may be used and distributed without restriction
// provided that this copyright statement is not removed from the file
// and that any derivative work contains the original copyright notice
// and the associated disclaimer.
//
// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED    
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//-----------------------------------------------------------------------------
// CRC module for data[7:0] ,   crc[15:0]=1+x^13+x^15+x^16;
//-----------------------------------------------------------------------------
module crc_modbus(
  input [7:0] data_in,
  input crc_en,
  output [15:0] crc_out,
  input rst,
  input clk);

  reg [15:0] lfsr_q,lfsr_c;

  assign crc_out = lfsr_q;

  always @(*) begin
    lfsr_c[0] = lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[12] ^ lfsr_q[15] ^ data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[4] ^ data_in[7];
    lfsr_c[1] = lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[13] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[5];
    lfsr_c[2] = lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[14] ^ data_in[2] ^ data_in[3] ^ data_in[4] ^ data_in[6];
    lfsr_c[3] = lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[15] ^ data_in[3] ^ data_in[4] ^ data_in[5] ^ data_in[7];
    lfsr_c[4] = lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[14] ^ data_in[4] ^ data_in[5] ^ data_in[6];
    lfsr_c[5] = lfsr_q[13] ^ lfsr_q[14] ^ lfsr_q[15] ^ data_in[5] ^ data_in[6] ^ data_in[7];
    lfsr_c[6] = lfsr_q[14] ^ lfsr_q[15] ^ data_in[6] ^ data_in[7];
    lfsr_c[7] = lfsr_q[15] ^ data_in[7];
    lfsr_c[8] = lfsr_q[0];
    lfsr_c[9] = lfsr_q[1];
    lfsr_c[10] = lfsr_q[2];
    lfsr_c[11] = lfsr_q[3];
    lfsr_c[12] = lfsr_q[4];
    lfsr_c[13] = lfsr_q[5] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[12] ^ lfsr_q[15] ^ data_in[0] ^ data_in[1] ^ data_in[2] ^ data_in[4] ^ data_in[7];
    lfsr_c[14] = lfsr_q[6] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[13] ^ data_in[1] ^ data_in[2] ^ data_in[3] ^ data_in[5];
    lfsr_c[15] = lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[11] ^ lfsr_q[14] ^ lfsr_q[15] ^ data_in[0] ^ data_in[1] ^ data_in[3] ^ data_in[6] ^ data_in[7];

  end // always

  always @(posedge clk, posedge rst) begin
    if(rst) begin
      lfsr_q <= {16{1'b1}};
    end
    else begin
      lfsr_q <= crc_en ? lfsr_c : lfsr_q;
    end
  end // always
endmodule // crc
Джеймс
Код
always @(posedge clk, posedge rst) begin
    if(rst) begin
      lfsr_q <= {16{1'b1}};
    end
    else begin
      lfsr_q <= crc_en ? lfsr_c : lfsr_q;
    end
  end // always


А сброс (rst) подается?
И здесь вообще говоря должен быть не только сброс при включении питания, поскольку так модуль отработает только один раз.

always @(posedge clk or posedge rst)
begin
if(rst) // power-up reset
lfsr_q[15:0] <= 16'hFFFF;
else
if (NEW_CRC)
lfsr_q[15:0] <= 16'hFFFF; // start new crc calculation
else
if (crc_en)
lfsr_q[15:0] <= lfsr_c[15:0];
end

И старайтесь указывать везде разрядности. Полезная привычка..
sergey sva
Может я что то не правильно понимаю для подсчета crc для Modbus RTU используется полином 0xA001 ? Для генерации кода если использовать сервисе http://outputlogic.com/?page_id=321 нужно выбрать
Нажмите для просмотра прикрепленного файла
После его использовать по такому алгоритму: Модуль uart ждет получения байта и держит crc в сбросе, как байт получен он поступает на datain снимаеться сигнал reset и устанавливает сигнал crccloc.
Следующей такт снимает crcclok. как следующий байт поступает опять ставиться crcclok и так пока весь пакет не будет получен. когда количество полученных байт соответствует, результат crc готов.
sergey sva
...
sergey sva
Блин ничего не понимаю, в чем я ошибся, или что то совсем ничего не понимаю, вроде такая простая вещь а не работает как нужно (.
Весь подсчет разбил что бы было удобнее искать проблему, но ничего так и не нашел. Взял проверенный алгоритм на C#
Код
        {
            int crc = 0xFFFF;
            byte[] msg = new byte[6];
            msg[0] = 0x24;
            msg[1] = 0x08;
            msg[2] = 0x00;
            msg[3] = 0x00;
            msg[4] = 0x00;
            msg[5] = 0x00;

            for (int j = 0; j < 6; j++)
            {
              

                crc = crc ^ msg[j];

                for (int i = 0; i < 8; i++)
                {

                    bool ff =  (crc & 1)==1;
                    crc = crc >> 1;

                    if (ff)
                    {
                        crc = crc ^ 0xA001;
                    }                    

                }
              
            }
        }

Результат получается правильный 0X3EE7.
Переписал практически один в один под Verilog, обмен с модулем crc_mobus проверил 10 раз все работает.
Результат правильный но сдвинут 0X003E. Почему так получается куда смотреть уже мыслей нет.
Код
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
module crc_mobus(input clck, input datacrcini,input datacrcnew, input[7:0]datain, output[15:0] crcout, output crcrd);
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
reg[15:0] countcrc      = 0;
reg[3:0] counterbytes   = 0;
reg[3:0] statucountcrc  = 0;

reg crcrdy     = 0;
reg loaddata   = 0;
reg bitlsb     = 0;
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
always @(posedge clck)
begin
    if(datacrcini)
    begin
        
        crcrdy          = 0;
        loaddata        = 0;
        statucountcrc   = 0;
        counterbytes    = 0;    
        countcrc[15:0]  = 16'b1111111111111111;
    end
    else if(datacrcnew) begin    
        if(loaddata == 0)
        begin
            loaddata      = 1;    
            crcrdy        = 0;
            counterbytes  = 0;                        
            countcrc[15:0] = {8'b00000000,datain[7:0]} ^countcrc[15:0];
            statucountcrc = 0;
        end
    end
    else begin        
        
        if(counterbytes < 8)
        begin
        
            case(statucountcrc)
            0:
            begin
                bitlsb = countcrc[0];
                statucountcrc = 1;
            end
            
            1:
            begin    
                countcrc  = countcrc>>1;                
                statucountcrc = 2;
            end
            
            2:
            begin
                if(bitlsb)
                begin
                    countcrc = countcrc ^ 16'b 1010000000000001;
                end                
                counterbytes  = counterbytes +1;
                statucountcrc = 0;                
            end
            
            default:
            begin
                statucountcrc = 0;
            end
            endcase    
            
        end
        else begin                
            crcrdy = 1;
            loaddata = 0;
        end
        
    end
    
end
//---------------------------------------------------------------------//
//---------------------------------------------------------------------//

assign crcout = countcrc;
assign crcrd  = crcrdy;
    
endmodule
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.