带VHDL的CRC16(多输入字节)

带VHDL的CRC16(多输入字节),vhdl,crc16,Vhdl,Crc16,下面的VHDL代码片段正确地获取了单个输入字节的16位CRC。 我如何将其扩展到多个输入字节,例如现在跨越的帧 要进行crc的128字节 注:函数“crc16”是使用一些在线工具生成的,但我自己也派生了它,所以我相信它可以正常工作。目前,下面的测试台为每个调用提供一个字节的CRC函数 CRC特征: CRC多项式:0x8005 反映的投入:是 反映的产出:是 种子值:0xFFFF 异或输出值:0xFFFF(IIUC,对CRC求反) 代码: ieee库; 使用ieee.std_logic_116

下面的VHDL代码片段正确地获取了单个输入字节的16位CRC。 我如何将其扩展到多个输入字节,例如现在跨越的帧 要进行crc的128字节

注:函数“crc16”是使用一些在线工具生成的,但我自己也派生了它,所以我相信它可以正常工作。目前,下面的测试台为每个调用提供一个字节的CRC函数

CRC特征:

  • CRC多项式:0x8005
  • 反映的投入:是
  • 反映的产出:是
  • 种子值:0xFFFF
  • 异或输出值:0xFFFF(IIUC,对CRC求反)
代码:

ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体crc是
端口(时钟:在标准逻辑中;
数据输入:标准逻辑向量(7到0);
crc输出:输出标准逻辑矢量(15到0)
);
结束crc;
crc的体系结构是
函数反向向量(v:标准逻辑向量中)
返回标准逻辑向量为
变量结果:标准逻辑向量(v’范围);
别名vr:std_逻辑_向量(v'反向_范围)为v;
开始
对于vr'范围循环中的i
结果(i):=vr(i);
端环;
返回结果;
结束;
功能crc16(数据i:在标准逻辑向量中(7到0);
crc_i:标准逻辑_向量(15到0))
返回标准逻辑向量为
变量crc_o:std_逻辑_向量(15到0);
开始
crc_o(15):=crc_i(7)xor crc_i(8)xor crc_i(9)xor crc_i(10)xor crc_i(11)xor crc_i(12)xor crc_i(13)xor crc_i(14)xor crc_i(15)xor
数据(0)异或数据(1)异或数据(2)异或数据(3)异或数据(4)异或数据(5)异或数据(6)异或数据(7);
crc_o(14):=crc_i(6);
crc_o(13):=crc_i(5);
crc_o(12):=crc_i(4);
crc_o(11):=crc_i(3);
crc_o(10):=crc_i(2);
crc_o(9):=crc_i(1)xor crc_i(15)xor data_i(7);
crc_o(8):=crc_i(0)xor crc_i(14)xor crc_i(15)xor data_i(6)xor data_i(7);
crc_o(7):=crc_i(13)xor crc_i(14)xor data_i(5)xor data_i(6);
crc_o(6):=crc_i(12)xor crc_i(13)xor data_i(4)xor data_i(5);
crc_o(5):=crc_i(11)xor crc_i(12)xor data_i(3)xor data_i(4);
crc_o(4):=crc_i(10)xor crc_i(11)xor data_i(2)xor data_i(3);
crc_o(3):=crc_i(9)xor crc_i(10)xor data_i(1)xor data_i(2);
crc_o(2):=crc_i(8)xor crc_i(9)xor data_i(0)xor data_i(1);
crc_o(1):=crc_i(9)xor crc_i(10)xor crc_i(11)xor crc_i(12)xor crc_i(13)xor crc_i(14)xor crc_i(15)xor
数据(1)异或数据(2)异或数据(3)异或数据(4)异或数据(5)异或数据(6)异或数据(7);
crc_o(0):=crc_i(8)xor crc_i(9)xor crc_i(10)xor crc_i(11)xor crc_i(12)xor crc_i(13)xor crc_i(14)xor crc_i(15)xor
数据(0)异或数据(1)异或数据(2)异或数据(3)异或数据(4)异或数据(5)异或数据(6)异或数据(7);
返回crc_o;
结束;
开始
crc_out“0”);
--输出
信号tb_crc_out:std_逻辑_矢量(15向下至0);
--时钟周期定义
恒定时钟周期:时间=10纳秒;
开始
--实例化被测单元(UUT)
uut:crc端口映射(
clk=>tb\U clk,
data_in=>tb_data_in,
crc\U out=>tb\U crc\U out
);
--时钟进程定义
clk_流程:流程
开始

tb_clk各种网站上常用的并行CRC生成器软件是开源的。我下载并将源从C++转换为C(声明类型为布尔类型、布尔值和值true和false)。p> 许可条款允许修改,同时保留版权声明。我删除了输出上的无效版权声明,并修复了免责声明中的一些注释字符,并修改了格式以适应。(我一直打算将输出也放入80列,在列中排列术语也会很有用)

它生成的代码与您的代码几乎相同:

crc gen vhdl 8 16 8005

这给了我们:

根据您在问题下的评论,这是x“01”、x“02”、x“03”和x“04”四个连续字节的正确值,即值x“D45E”

那么让我们将其应用到您的代码中

首先是变化:

library ieee; 
use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

entity crc is 
port ( clk: in std_logic;
       data_in: in std_logic_vector(7 downto 0); 
       crc_en:   in  std_logic;   -- ADDED
       rst:      in  std_logic;   -- ADDED
       crc_out: out std_logic_vector(15 downto 0)
      );
end crc;

architecture crc_arch of crc is     

function reverse_vector(v: in std_logic_vector)
return std_logic_vector is
    variable result: std_logic_vector(v'RANGE);
    alias vr: std_logic_vector(v'REVERSE_RANGE) is v;
begin
    for i in vr'RANGE loop
        result(i) := vr(i);
    end loop;

    return result;
end;    


function crc16( data_i: in std_logic_vector(7 downto 0);             
                     crc_i: in std_logic_vector(15 downto 0))
return std_logic_vector is  
    variable crc_o: std_logic_vector(15 downto 0);
begin
    crc_o(15) := crc_i(7) xor crc_i(8) xor crc_i(9) xor crc_i(10) xor crc_i(11) xor crc_i(12) xor crc_i(13) xor crc_i(14) xor crc_i(15) xor 
                    data_i(0) xor data_i(1) xor data_i(2) xor data_i(3) xor data_i(4) xor data_i(5) xor data_i(6) xor data_i(7);          
    crc_o(14) := crc_i(6);      
    crc_o(13) := crc_i(5);
    crc_o(12) := crc_i(4);
    crc_o(11) := crc_i(3);  
    crc_o(10) := crc_i(2);  
    crc_o(9)  := crc_i(1) xor crc_i(15) xor data_i(7);
    crc_o(8)  := crc_i(0) xor crc_i(14) xor crc_i(15) xor data_i(6) xor data_i(7);
    crc_o(7)  := crc_i(13) xor crc_i(14) xor data_i(5) xor data_i(6);
    crc_o(6)  := crc_i(12) xor crc_i(13) xor data_i(4) xor data_i(5);               
    crc_o(5)  := crc_i(11) xor crc_i(12) xor data_i(3) xor data_i(4);
    crc_o(4)  := crc_i(10) xor crc_i(11) xor data_i(2) xor data_i(3);
    crc_o(3)  := crc_i(9) xor crc_i(10) xor data_i(1) xor data_i(2);
    crc_o(2)  := crc_i(8) xor crc_i(9) xor data_i(0) xor data_i(1);
    crc_o(1)  := crc_i(9) xor crc_i(10) xor crc_i(11) xor crc_i(12) xor crc_i(13) xor crc_i(14) xor crc_i(15) xor 
                    data_i(1) xor data_i(2) xor data_i(3) xor data_i(4) xor data_i(5) xor data_i(6) xor data_i(7);
    crc_o(0)  := crc_i(8) xor crc_i(9) xor crc_i(10) xor crc_i(11) xor crc_i(12) xor crc_i(13) xor crc_i(14) xor crc_i(15) xor 
                    data_i(0) xor data_i(1) xor data_i(2) xor data_i(3) xor data_i(4) xor data_i(5) xor data_i(6) xor data_i(7);

    return crc_o;

end;

    signal crc_o:   std_logic_vector (15 downto 0);  -- ADDED register

begin 

    -- crc_out <= not reverse_vector(crc16(reverse_vector(data_in), x"FFFF"));

    process (clk)  -- ADDED process
    begin
        if rst = '1' then
            crc_o <= x"FFFF";
        elsif rising_edge(clk) then  
            if crc_en = '1' then
                crc_o <= crc16(reverse_vector(data_in), crc_o);
            end if;
        end if;
    end process;

    crc_out <= not reverse_vector(crc_o);  -- ADDED

end architecture crc_arch;
所有的变化都是减法的

这就产生了:

答案与使用下载/生成的VHDL代码相同


因此,使用crc16函数调用的秘诀是不要对crc16函数调用的crc_i参数的返回值进行任何反转或反转。

您可能需要看看这个通用实现:。使用可用的、已经测试过的实现通常会更好。实际上,在线上有一个很好的示例(不使用函数调用)。请参阅USB 2.0的数据宽度8、多项式宽度16和协议CRC16(与0x8005相同)。第二个选项卡将允许您生成VHDL示例代码(我认为美国版权法规定,按下按钮的人是作者,这意味着版权声明可能无效)。它以任何方式显示了如何在每个时钟上引入成功的字节并生成crc。OutputLogic.com使用的VHDL crc生成器的声称源代码可以通过登录从opencores下载(需要注册)。crc是一种逐位操作。多项式应用于输入向量的每一位。这意味着您的代码是一个展开循环,由对输入字的位0到15执行的16个CRC单位计算组成。要处理更多的位,您可以进一步展开它(Fmax将减少),或者在每个时钟周期插入下一个字。这就是我所做的。请注意对生成器多项式
位进行移位和异或的次数。@user1155120:我刚刚检查了“outputlogic”站点。看起来USB-CRC16和我使用的那个有相同的属性。但是,该站点的HDL与我已知的良好测试用例不匹配,例如,字节模式0x1 0x2 0x3 0x4应导致CRC为0xD45E(结果被反射和否定)。你是谁
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY tb_crc IS
END tb_crc;

ARCHITECTURE behavior OF tb_crc IS 

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT crc
PORT(
        clk: std_logic;
     data_in : IN  std_logic_vector(7 downto 0);
     crc_out : OUT  std_logic_vector(15 downto 0)
    );
END COMPONENT;


--Inputs
signal tb_clk : std_logic := '0';
signal tb_data_in : std_logic_vector(7 downto 0) := (others => '0');

--Outputs
signal tb_crc_out : std_logic_vector(15 downto 0);

-- Clock period definitions
constant clk_period : time := 10 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)
uut: crc PORT MAP (
         clk => tb_clk,
      data_in => tb_data_in,
      crc_out => tb_crc_out
    );

-- Clock process definitions
clk_process :process
begin
    tb_clk <= '1';
    wait for clk_period/2;
    tb_clk <= '0';
    wait for clk_period/2;
end process;

-- Stimulus process
stim_proc: process
begin       
  -- hold reset state for 100 ns.
  wait for 100 ns;  


  -- insert stimulus here

    tb_data_in <= x"01";        
    wait for clk_period;

    tb_data_in <= x"02";
    wait for clk_period;

    tb_data_in <= x"03";
    wait for clk_period;

    tb_data_in <= x"04";
    wait for clk_period;

    wait;
end process;

END;
------------------------------------------------------------------------------- 
-- 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 entity/architecture for
-- data(7:0)
-- crc(15:0) = 1+x^2+x^15+x^16;
--
library ieee;
use ieee.std_logic_1164.all;

entity crc is
    port (
        data_in:  in  std_logic_vector (7 downto 0);
        crc_en:   in  std_logic;
        rst:      in  std_logic;
        clk:      in  std_logic;
        crc_out:  out std_logic_vector (15 downto 0)
    );
end entity crc;

architecture imp_crc of crc is
    signal lfsr_q: std_logic_vector (15 downto 0);
    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);

REGISTERS:
    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;
end architecture imp_crc;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity crc_tb is
end entity;

architecture  foo of crc_tb is

    function reverse_vector(v: in std_logic_vector)
    return std_logic_vector is
        variable result: std_logic_vector(v'RANGE);
        alias vr: std_logic_vector(v'REVERSE_RANGE) is v;
    begin
        for i in vr'RANGE loop
            result(i) := vr(i);
        end loop;

        return result;
    end;    

    signal datain:   std_logic_vector (7 downto 0);
    signal data_in:  std_logic_vector (7 downto 0);
    signal crc_en:   std_logic := '0';
    signal rst:      std_logic;
    signal clk:      std_logic := '0';
    signal crc_out:  std_logic_vector (15 downto 0);

    signal crcout:   std_logic_vector (15 downto 0);
begin

    crcout <= not reverse_vector (crc_out);

DUT:
    entity work.crc
        port map (
            data_in => data_in,
            crc_en => crc_en,
            rst => rst,
            clk => clk,
            crc_out => crc_out
        );

CLOCK:
    process 
    begin
        wait for 5 ns; -- half the clock period
        clk <= not clk;
        if now > 160 ns then
            wait;
        end if;
    end process;
    STIMULI:
    process
    begin
        rst <= '1';
        for i in 0 to 9 loop
            wait until rising_edge(clk);
        end loop;
        rst <= '0';
        crc_en <= '1';
        for i in 1 to 4 loop
            datain <= std_logic_vector(to_unsigned (i,8));
            data_in <= reverse_vector (std_logic_vector(to_unsigned(i,8)));
            wait until rising_edge(clk);
        end loop;
        crc_en <= '0';
        wait until rising_edge(clk);
        wait;
    end process;
end architecture;
library ieee; 
use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

entity crc is 
port ( clk: in std_logic;
       data_in: in std_logic_vector(7 downto 0); 
       crc_en:   in  std_logic;   -- ADDED
       rst:      in  std_logic;   -- ADDED
       crc_out: out std_logic_vector(15 downto 0)
      );
end crc;

architecture crc_arch of crc is     

function reverse_vector(v: in std_logic_vector)
return std_logic_vector is
    variable result: std_logic_vector(v'RANGE);
    alias vr: std_logic_vector(v'REVERSE_RANGE) is v;
begin
    for i in vr'RANGE loop
        result(i) := vr(i);
    end loop;

    return result;
end;    


function crc16( data_i: in std_logic_vector(7 downto 0);             
                     crc_i: in std_logic_vector(15 downto 0))
return std_logic_vector is  
    variable crc_o: std_logic_vector(15 downto 0);
begin
    crc_o(15) := crc_i(7) xor crc_i(8) xor crc_i(9) xor crc_i(10) xor crc_i(11) xor crc_i(12) xor crc_i(13) xor crc_i(14) xor crc_i(15) xor 
                    data_i(0) xor data_i(1) xor data_i(2) xor data_i(3) xor data_i(4) xor data_i(5) xor data_i(6) xor data_i(7);          
    crc_o(14) := crc_i(6);      
    crc_o(13) := crc_i(5);
    crc_o(12) := crc_i(4);
    crc_o(11) := crc_i(3);  
    crc_o(10) := crc_i(2);  
    crc_o(9)  := crc_i(1) xor crc_i(15) xor data_i(7);
    crc_o(8)  := crc_i(0) xor crc_i(14) xor crc_i(15) xor data_i(6) xor data_i(7);
    crc_o(7)  := crc_i(13) xor crc_i(14) xor data_i(5) xor data_i(6);
    crc_o(6)  := crc_i(12) xor crc_i(13) xor data_i(4) xor data_i(5);               
    crc_o(5)  := crc_i(11) xor crc_i(12) xor data_i(3) xor data_i(4);
    crc_o(4)  := crc_i(10) xor crc_i(11) xor data_i(2) xor data_i(3);
    crc_o(3)  := crc_i(9) xor crc_i(10) xor data_i(1) xor data_i(2);
    crc_o(2)  := crc_i(8) xor crc_i(9) xor data_i(0) xor data_i(1);
    crc_o(1)  := crc_i(9) xor crc_i(10) xor crc_i(11) xor crc_i(12) xor crc_i(13) xor crc_i(14) xor crc_i(15) xor 
                    data_i(1) xor data_i(2) xor data_i(3) xor data_i(4) xor data_i(5) xor data_i(6) xor data_i(7);
    crc_o(0)  := crc_i(8) xor crc_i(9) xor crc_i(10) xor crc_i(11) xor crc_i(12) xor crc_i(13) xor crc_i(14) xor crc_i(15) xor 
                    data_i(0) xor data_i(1) xor data_i(2) xor data_i(3) xor data_i(4) xor data_i(5) xor data_i(6) xor data_i(7);

    return crc_o;

end;

    signal crc_o:   std_logic_vector (15 downto 0);  -- ADDED register

begin 

    -- crc_out <= not reverse_vector(crc16(reverse_vector(data_in), x"FFFF"));

    process (clk)  -- ADDED process
    begin
        if rst = '1' then
            crc_o <= x"FFFF";
        elsif rising_edge(clk) then  
            if crc_en = '1' then
                crc_o <= crc16(reverse_vector(data_in), crc_o);
            end if;
        end if;
    end process;

    crc_out <= not reverse_vector(crc_o);  -- ADDED

end architecture crc_arch;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity crc_tb is
end entity;

architecture  foo of crc_tb is

    signal data_in:  std_logic_vector (7 downto 0);
    signal crc_en:   std_logic := '0';
    signal rst:      std_logic;
    signal clk:      std_logic := '0';
    signal crc_out:  std_logic_vector (15 downto 0);

begin

DUT:
    entity work.crc
        port map (
            data_in => data_in,
            crc_en => crc_en,
            rst => rst,
            clk => clk,
            crc_out => crc_out
        );

CLOCK:
    process 
    begin
        wait for 5 ns; -- half the clock period
        clk <= not clk;
        if now > 160 ns then
            wait;
        end if;
    end process;
STIMULI:
    process
    begin
        rst <= '1';
        for i in 0 to 9 loop
            wait until rising_edge(clk);
        end loop;
        rst <= '0';
        crc_en <= '1';
        for i in 1 to 4 loop
            data_in <= std_logic_vector(to_unsigned (i,8));
            wait until rising_edge(clk);
        end loop;
        crc_en <= '0';
        wait until rising_edge(clk);
        wait;
    end process;
end architecture;