Jump to content

    

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

Recommended Posts

jenya7
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;
}

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

Share this post


Link to post
Share on other sites

new123

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

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

 

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

Edited by new123

Share this post


Link to post
Share on other sites

jenya7
4 minutes ago, new123 said:

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

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

 

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

 

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

Share this post


Link to post
Share on other sites

new123

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

Share this post


Link to post
Share on other sites

des00
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

 

Share this post


Link to post
Share on other sites

jenya7

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

 

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

Edited by jenya7

Share this post


Link to post
Share on other sites

sazh
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").

 

Share this post


Link to post
Share on other sites

esokol
12 hours ago, jenya7 said:

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

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

 

crc16_test.c

Share this post


Link to post
Share on other sites

jenya7
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

Edited by jenya7

Share this post


Link to post
Share on other sites

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
}

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

Edited by jenya7

Share this post


Link to post
Share on other sites

sazh
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)

Share this post


Link to post
Share on other sites

jenya7
12 hours ago, sazh said:

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

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

Share this post


Link to post
Share on other sites

sazh

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

На базе полинома сваять сдвигающий регистр с нужными отводами по 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
 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.