jenya7 0 Posted March 14 · Report post 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; } как то не особо похож. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
new123 0 Posted March 14 (edited) · Report post Исполнение вашего crc16 usb в двух видах: табличное и прямое вычисление https://programmersought.com/article/84488802461/ ps. Если вы чисто для само проверки самого себя, то лучше конечно заюзать online вычислялки. Но если вам на лету надо, то да, лучше си Edited March 14 by new123 Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jenya7 0 Posted March 14 · Report post 4 minutes ago, new123 said: Исполнение вашего crc16 usb в двух видах: табличное и прямое вычисление https://programmersought.com/article/84488802461/ ps. Если вы чисто для само проверки самого себя, то лучше конечно заюзать online вычислялки. Но если вам на лету надо, то да, лучше си спасибо. мне конечно без таблицы так как VHDL модуль без таблицы. мне си код нужен потому как посылка пакетов между FPGA и CPU. На стороне CPU нужен си аналог вычисления CRC. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
new123 0 Posted March 14 · Report post если вы вдруг делаете из под своего драйвера в linux kernel, то там готовая функция есть crc16. Но это на всякий случай Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
des00 1 Posted March 14 · Report post 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 Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jenya7 0 Posted March 14 (edited) · Report post vhdl версия результат 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? ошибся. каждый клок переписывает значение. надо так но всё равно результаты разные. Edited March 14 by jenya7 Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
sazh 0 Posted March 14 · Report post 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"). Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
esokol 0 Posted March 14 · Report post 12 hours ago, jenya7 said: Начал делать Си аналог модуля - выходит как то монструозно. Сделайте сначала "в лоб", а потом уже оптимизируйте. Код выглядит примерно так (в соответствии с модулем из первого сообщения): crc16_test.c Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jenya7 0 Posted March 15 (edited) · Report post 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 March 15 by jenya7 Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jenya7 0 Posted March 15 (edited) · Report post 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 March 15 by jenya7 Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
sazh 0 Posted March 16 · Report post 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) Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
jenya7 0 Posted March 17 · Report post 12 hours ago, sazh said: Можно конечный вариант посмотреть. С тестбенчем на посылку c 8'h31 по 8'h39. ( не силен я в VHDL) конечный вариант Си или VHDL? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
sazh 0 Posted March 17 · Report post Причем тут Си. Пошлите его по углу и по азимуту. Вам предложили инженерный подход. Без всяких калькуляторов. На базе полинома сваять сдвигающий регистр с нужными отводами по 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 Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...