Перейти к содержанию
    

Применить CRC для массива.

12 minutes ago, fguy said:

алгоритм вроде как один - разные только полиномы

не знаю. если взять сгенерированный код

architecture behavior of CRC16 is

signal lfsr_q: std_logic_vector (15 downto 0) := (others => '1');
signal lfsr_c: std_logic_vector (15 downto 0);
	 
begin

    crc_out <= lfsr_q;

    lfsr_c(0) <= lfsr_q(8) xor lfsr_q(9) xor lfsr_q(10) xor lfsr_q(11) xor 
                 lfsr_q(12) xor lfsr_q(13) xor lfsr_q(14) xor lfsr_q(15) xor 
                 data_in(0) xor data_in(1) xor data_in(2) xor data_in(3) xor 
                 data_in(4) xor data_in(5) xor data_in(6) xor data_in(7);
    lfsr_c(1) <= lfsr_q(9) xor lfsr_q(10) xor lfsr_q(11) xor lfsr_q(12) xor 
                 lfsr_q(13) xor lfsr_q(14) xor lfsr_q(15) xor data_in(1) xor 
                 data_in(2) xor data_in(3) xor data_in(4) xor data_in(5) xor 
                 data_in(6) xor data_in(7);
    lfsr_c(2) <= lfsr_q(8) xor lfsr_q(9) xor data_in(0) xor data_in(1);
    lfsr_c(3) <= lfsr_q(9) xor lfsr_q(10) xor data_in(1) xor data_in(2);
    lfsr_c(4) <= lfsr_q(10) xor lfsr_q(11) xor data_in(2) xor data_in(3);
    lfsr_c(5) <= lfsr_q(11) xor lfsr_q(12) xor data_in(3) xor data_in(4);
    lfsr_c(6) <= lfsr_q(12) xor lfsr_q(13) xor data_in(4) xor data_in(5);
    lfsr_c(7) <= lfsr_q(13) xor lfsr_q(14) xor data_in(5) xor data_in(6);
    lfsr_c(8) <= lfsr_q(0) xor lfsr_q(14) xor lfsr_q(15) xor data_in(6) xor 
                 data_in(7);
    lfsr_c(9) <= lfsr_q(1) xor lfsr_q(15) xor 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) xor lfsr_q(8) xor lfsr_q(9) xor lfsr_q(10) xor 
                  lfsr_q(11) xor lfsr_q(12) xor lfsr_q(13) xor lfsr_q(14) xor 
                  lfsr_q(15) xor data_in(0) xor data_in(1) xor data_in(2) xor 
                  data_in(3) xor data_in(4) xor data_in(5) xor data_in(6) xor 
                  data_in(7);
						
						
process (CLK, RST)
    begin
        if RST = '1' then
            lfsr_q   <= (others => '1');
        elsif rising_edge(CLK) then
            if CRC_EN = '1' then
                lfsr_q <= lfsr_c;
            end if;
        end if;
    end process;		

то ближайший что я нашел

unsigned short crc16(const unsigned char* data_p, unsigned char length)
{
    unsigned char x;
    unsigned short crc = 0xFFFF;

    while (length--)
    {
        x = crc >> 8 ^ *data_p++;
        x ^= x>>4;
        crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
    }
    return crc;
}

как то не особо похож.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Исполнение вашего crc16 usb в двух видах: табличное и прямое вычисление

https://programmersought.com/article/84488802461/

 

ps. Если вы чисто для само проверки самого себя, то лучше конечно заюзать online вычислялки. Но если вам на лету надо, то да, лучше си

Изменено пользователем new123

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, new123 said:

Исполнение вашего crc16 usb в двух видах: табличное и прямое вычисление

https://programmersought.com/article/84488802461/

 

ps. Если вы чисто для само проверки самого себя, то лучше конечно заюзать online вычислялки. Но если вам на лету надо, то да, лучше си

 

спасибо. мне конечно без таблицы так как VHDL модуль без таблицы. мне си код нужен потому как посылка пакетов между FPGA и CPU. На стороне CPU нужен си аналог вычисления CRC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если вы вдруг делаете из под своего драйвера в linux kernel, то там готовая функция есть crc16. Но это на всякий случай

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 minutes ago, jenya7 said:

не знаю. если взять сгенерированный код

Потому что это развернутый, чужой код. А вы могли бы сделать свой свернутый код для одного бита и применить его к байту. вот первое что попалось по руку

  //
  // G(x) = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + 1
  //
  function bit [31:0] crc_32x1 (input bit [31:0] crc, input bit d);
    bit msb;
  begin
    msb       = crc[31];
    crc_32x1  = crc << 1;

    crc_32x1[ 0] = d ^ msb;
    crc_32x1[ 1] = d ^ msb ^ crc[ 0];
    crc_32x1[ 2] = d ^ msb ^ crc[ 1];
    crc_32x1[ 4] = d ^ msb ^ crc[ 3];
    crc_32x1[ 5] = d ^ msb ^ crc[ 4];
    crc_32x1[ 7] = d ^ msb ^ crc[ 6];
    crc_32x1[ 8] = d ^ msb ^ crc[ 7];
    crc_32x1[10] = d ^ msb ^ crc[ 9];
    crc_32x1[11] = d ^ msb ^ crc[10];
    crc_32x1[12] = d ^ msb ^ crc[11];
    crc_32x1[16] = d ^ msb ^ crc[15];
    crc_32x1[22] = d ^ msb ^ crc[21];
    crc_32x1[23] = d ^ msb ^ crc[22];
    crc_32x1[26] = d ^ msb ^ crc[25];
  end
  endfunction
  //
  //
  //
  function bit [31:0] crc_32x8(input bit [31:0] crc, input bit [7:0] data);
    int i;
  begin
    crc_32x8 = crc;
    for (i = 8; i > 0; i--) begin
      crc_32x8 = crc_32x1 (crc_32x8, data[i-1]);
    end
  end
  endfunction

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

vhdl версия

crc.thumb.png.6a84df1c23e0bb923d3073e59059ef3a.png

результат 0х5А82

Си версия


unsigned short crc(unsigned char *ptr, int len)
{
    unsigned int i;
    unsigned short crc = 0xffff;
    
    while(len--)
    {
        crc ^= *ptr++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xA001;
            else
                crc = (crc >> 1);
        }
    }
    
    return ~crc;
}


unsigned short crc_res;
unsigned char crc_data[3] = {1,2,3};

crc_res = crc(crc_data, 3);

результат 0х9Е9Е

 

несостыковочка однако

 

эта строка меняет результат

crc = (crc >> 1) ^ 0xA001;

откуда взялось 0xA001?

 

ошибся. каждый клок переписывает значение. надо так

crc.thumb.png.64c8b6cca5e4563bab20fc88bd4a5eb7.png

 

но всё равно результаты разные.

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, jenya7 сказал:

в смысле подходящий? алгоритмы передающего и принимающего должны совпадать.

А каком алгоритме идет речь?  Чтоб всем понятно было. Например:

пример спецификации популярного варианта алгоритма "CRC 16"

CRC16 стандартный: 1-1000-0000-0000-0101

Name : "CRC 16"

Width : 16

Poly : 8005    x^16 + x^15 + x^2 + 1

Init : 0000

RefIn : True

RefOut : True

XorOut : 0000

Check : BB3D    ASCII строки "123456789" (шестнадцатеричные значение "31_32_… 39").

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 hours ago, jenya7 said:

Начал делать Си аналог модуля - выходит как то монструозно.

Сделайте сначала "в лоб", а потом уже оптимизируйте. Код выглядит примерно так (в соответствии с модулем из первого сообщения):

 

crc16_test.c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 hours ago, sazh said:

А каком алгоритме идет речь?  Чтоб всем понятно было. Например:

пример спецификации популярного варианта алгоритма "CRC 16"

CRC16 стандартный: 1-1000-0000-0000-0101

Name : "CRC 16"

Width : 16

Poly : 8005    x^16 + x^15 + x^2 + 1

Init : 0000

RefIn : True

RefOut : True

XorOut : 0000

Check : BB3D    ASCII строки "123456789" (шестнадцатеричные значение "31_32_… 39").

 

Си вариант именно такой

CRC algorithm name                CRC-16/USB

Polynomial formula                  x16 + x15 + x2 + 1

width                                   16

Polynomial                            8005

Initial value                           FFFF

Results are different or values  FFFF

Input reverse                       true

Output reverse                     true

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 hours ago, esokol said:

Сделайте сначала "в лоб", а потом уже оптимизируйте. Код выглядит примерно так (в соответствии с модулем из первого сообщения):

 

crc16_test.c 2.63 kB · 3 downloads

спасибо. так, "в лоб" результаты совпадают.

unsigned short crc_res;
unsigned char crc_data[3] = {1,2,3};

int main()
{    
    crc16_8(1, crc_data[0]);
    for (int i = 0; i < 3; i++)
    {
        crc_res = crc16_8(0, crc_data[i]);
    }
    
  //crc_res = 0x821D
}

надеюсь меня тапками не закидают на Си стороне. ))

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15.03.2022 в 09:49, jenya7 сказал:

спасибо. так, "в лоб" результаты совпадают.


unsigned short crc_res;
unsigned char crc_data[3] = {1,2,3};

int main()
{    
    crc16_8(1, crc_data[0]);
    for (int i = 0; i < 3; i++)
    {
        crc_res = crc16_8(0, crc_data[i]);
    }
    
  //crc_res = 0x821D
}

надеюсь меня тапками не закидают на Си стороне. ))

 

Можно конечный вариант посмотреть. С тестбенчем на посылку c 8'h31 по 8'h39. ( не силен я в VHDL)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 hours ago, sazh said:

Можно конечный вариант посмотреть. С тестбенчем на посылку c 8'h31 по 8'h39. ( не силен я в VHDL)

конечный вариант Си или VHDL?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Причем тут Си. Пошлите его по углу и по азимуту. Вам предложили инженерный подход. Без всяких калькуляторов.

На базе полинома сваять сдвигающий регистр с нужными отводами по xor и отдать на откуп синтезатору байтовую реализацию входных данных.

При этом ваш crc16 проект должен удовлетворять как передатчик (налету прогонять массив данных и подставлять в конце массива два байта crc),

так и приемник (налету прогонять массив данных с двумя байтами crc, получая сигнатуру (которая известна и всегда одна и та же для конкретной реализации полинома). При этом после вычислений  crc16 регистр должен устанавливаться за два такта в состояние ffff, чтоб не дергать его входным сигналом инициализации).

////////////////////////////////////////////////////////////////////////////////////////
//G(x) = x16 + x15 + x2 + 1
////////////////////////////////////////////////////////////////////////////////////////
// Module Name = crc_16_8_usb
// CRC Width = 16
// Data Width = 8
// CRC Init   = ffff
// RefIn = true
// RefOut = true
// Polynomial = 8005
// Check = B4C8 (8'h31, 8'h32....8'h39)
// Check with magic world = B001
module crc_16_8_usb
(
input   [7:0] ibyte,
input         calc,
input         init,
input         clk,
output [15:0] crc_rg,
output  [7:0] crc_check_rg,
output [15:0] crc_check16
);
      
reg [15:0] crc_reg = 16'hffff;
reg  [7:0] crc_check_reg = 8'hff;

wire [15:0] next_crc;

//////////////////////////////////////////////////////////////////////////////
// CRC XOR equations
//////////////////////////////////////////////////////////////////////////////    
function [15:0] crc_16x1 (input [15:0] crc, input d);
reg msb;

begin
msb = crc[15];
crc_16x1 = crc << 1;

crc_16x1[0]  = d ^ msb;
crc_16x1[2]  = d ^ msb ^ crc[1];
crc_16x1[15] = d ^ msb ^ crc[14];
end
endfunction


function [15:0] crc_16_8 (input [15:0] crc, input [7:0] data);
integer i;

begin
crc_16_8 = crc;
for (i = 0; i < 8; i= i + 1)    // RefIn = true
begin
crc_16_8 = crc_16x1(crc_16_8, data);
end
end
endfunction
///////////////////////////////////////////////////////////////////////////////////

assign next_crc = crc_16_8(crc_reg, ibyte);

always @ (posedge clk)
begin
if (init)
    begin
    crc_reg <= 16'hffff;
    crc_check_reg <= 8'hff;
    end
else if (calc)
    begin
    crc_reg <= crc_16_8(crc_reg, ibyte);
    crc_check_reg <= ~{next_crc[8], next_crc[9], next_crc[10], next_crc[11],   // RefOut = true
                             next_crc[12], next_crc[13], next_crc[14], next_crc[15]};                                                  
    end
else
    begin
    crc_reg <= {crc_reg[7:0], 8'hff};
    crc_check_reg <= ~{crc_reg[0], crc_reg[1], crc_reg[2], crc_reg[3],      // RefOut = true
                             crc_reg[4], crc_reg[5], crc_reg[6], crc_reg[7]};
    end
end

assign crc_check_rg = crc_check_reg;

//////////////////////////
genvar i;
generate for (i = 0; i < 16; i = i + 1)
begin : block
assign crc_check16 = ~crc_reg[15-i];    // RefOut = true
assign crc_rg = crc_reg[15-i];
end 
endgenerate
///////////////////////

endmodule

 

`timescale 1 ns / 1 ps
module crc_16_8_usb_tb;

parameter halfperiod_100 = 5.0;    // 100 MHz

reg   [7:0] ibyte = 8'h00;
reg         calc = 1'b0;
reg         init = 1'b0;
reg         clk;
wire [15:0] crc_rg;
wire  [7:0] crc_check_rg;
wire [15:0] crc_check16;


initial begin : clock_generator_100
clk = 1'b0;
forever #(halfperiod_100) clk = ~clk;
end

initial begin
                                repeat (4) @(posedge clk);

init = 1'b1;                repeat (4) @(posedge clk);
init = 1'b0;                repeat (4) @(posedge clk);

{ibyte, calc} = {8'h31, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h32, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h33, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h34, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h35, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h36, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h37, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h38, 1'b1};        repeat (1) @(posedge clk); 
{ibyte, calc} = {8'h39, 1'b1};        repeat (1) @(posedge clk); 
{ibyte, calc} = {8'h00, 1'b0};        repeat (6) @(posedge clk);// Check : B4C8


{ibyte, calc} = {8'h31, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h32, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h33, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h34, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h35, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h36, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h37, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h38, 1'b1};        repeat (1) @(posedge clk); 
{ibyte, calc} = {8'h39, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'hc8, 1'b1};        repeat (1) @(posedge clk);// Check : B4C8 
{ibyte, calc} = {8'hb4, 1'b1};        repeat (1) @(posedge clk);//
{ibyte, calc} = {8'h00, 1'b0};        repeat (6) @(posedge clk);//  Check : 4FFE 
                                                    //magic world : B001

{ibyte, calc} = {8'h31, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h32, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h33, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h34, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h35, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h36, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h37, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'h38, 1'b1};        repeat (1) @(posedge clk); 
{ibyte, calc} = {8'h39, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'hc8, 1'b1};        repeat (1) @(posedge clk); 
{ibyte, calc} = {8'hb4, 1'b1};        repeat (1) @(posedge clk);
{ibyte, calc} = {8'hfe, 1'b1};        repeat (1) @(posedge clk);// Check : 4FFE 
{ibyte, calc} = {8'h4f, 1'b1};        repeat (1) @(posedge clk);//
{ibyte, calc} = {8'h00, 1'b0};        repeat (6) @(posedge clk);
                                                    // magic world : B001

#5 $display ("End");
$stop;
end


crc_16_8_usb
    crc_16_8_usb_inst
    (
    .ibyte                    (ibyte),
    .calc                        (calc),
    .init                        (init),
    .clk                        (clk),
    .crc_rg                    (crc_rg),
    .crc_check_rg            (crc_check_rg),
    .crc_check16            (crc_check16)
    );

endmodule
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...