07-29-2019 06:36 AM
I hope I am in the right forum.
I own a Zynq 7Z020.
I want to design a CRC calculation using hardware. The data should come from the software. I also want to implement a software start bit. The whole thing should be designed via an IP core.
An example I wanted to initially implement the following:
Polynomial: 6Bit (110101) = - lsr (5: 0) = 1 + x ^ 2 + x ^ 4 + x ^ 5 + x ^ 6;
I found the following generator for the VHDL code. http://outputlogic.com/?page_id=321
I created the following VHDL code from the code:
entity myCRC5bit is Port ( clk : in STD_LOGIC; data_in : in STD_LOGIC_VECTOR (4 downto 0); rst : in STD_LOGIC; srt : in STD_LOGIC; crc_out : out STD_LOGIC_VECTOR (5 downto 0); data_out : out STD_LOGIC_VECTOR (5 downto 0)); end myCRC5bit; architecture Behavioral of myCRC5bit is signal lfsr_q: std_logic_vector (5 downto 0); signal lfsr_c: std_logic_vector (5 downto 0); begin data_out <= "101010"; crc_out <= lfsr_q; lfsr_c(0) <= lfsr_q(1) xor lfsr_q(2) xor lfsr_q(4) xor data_in(0) xor data_in(1) xor data_in(3); lfsr_c(1) <= lfsr_q(2) xor lfsr_q(3) xor lfsr_q(5) xor data_in(1) xor data_in(2) xor data_in(4); lfsr_c(2) <= lfsr_q(1) xor lfsr_q(2) xor lfsr_q(3) xor data_in(0) xor data_in(1) xor data_in(2); lfsr_c(3) <= lfsr_q(2) xor lfsr_q(3) xor lfsr_q(4) xor data_in(1) xor data_in(2) xor data_in(3); lfsr_c(4) <= lfsr_q(1) xor lfsr_q(2) xor lfsr_q(3) xor lfsr_q(5) xor data_in(0) xor data_in(1) xor data_in(2) xor data_in(4); lfsr_c(5) <= lfsr_q(0) xor lfsr_q(1) xor lfsr_q(3) xor data_in(0) xor data_in(2); pl_clk: process (clk,rst) begin if (rst = '1') then lfsr_q <= b"111111"; elsif (clk'EVENT and clk = '1') then if (srt = '1') then lfsr_q <= lfsr_c; end if; end if; end process pl_clk; end Behavioral;
Have subsequently created an IP core (AXI-4Lite).
I then connected the component to the core and mapped it.
U_myCRC5bit: myCRC5bit port map( clk => S_AXI_ACLK, data_in => slv_reg0(6 downto 2), rst => slv_reg0(1), srt => slv_reg0(0), crc_out => ocrc, data_out => dcrc);
And the adress decoding:
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB); case loc_addr is when b"00" => reg_data_out <= slv_reg0; when b"01" => reg_data_out(5 downto 0) <= ocrc; when b"10" => reg_data_out <= slv_reg2; when b"11" => reg_data_out <= slv_reg3; when others => reg_data_out <= (others => '0'); end case; end process;
In a new Vivado project, I added the IP over the IP repo and connected it to the processor, then generated the bitstream and then forwarded it to SDK.
From the software side, I have the following code to test:
6d: (1101101; 11011 = Data; 0 = RST; 1 = SRT).
u32 ocrc; Xil_Out32(XPAR_MYIPCRC5BIT_0_S00_AXI_BASEADDR, 0x0000006D); ocrc = Xil_In32(XPAR_MYIPCRC5BIT_0_S00_AXI_BASEADDR+4); xil_printf("CRC=%d\n\r", ocrc);
Now I do not get the expected result (00101). Where can I find my mistake, can someone help me on the jump?
07-29-2019 07:23 AM
Have you simulated sending this AXI-lite request to your design? Do you have a simulated waveform showing what the transaction is *supposed* to look like? That's where many folks start when trying to debug an interaction like this one.
Alternatively, you could attach an internal logic analyzer (ILA) to your design to do (roughly) the same thing, but this time using the actual logic and timing from within your design.
Neither of these approaches would be my first go-to approach. For me, I'd start with formal verification. I've just seen too many poorly implemented AXI-lite cores that have passed simulation to trust simulation. You can find an example of a formally verified RGMII CRC calculator here, as an example. It doesn't have the AXI-lite interface though. I think the liteeth core has an example of a CRC core using an AXI-stream interface. That'd be another example, and perhaps even a touch closer to what you are trying to accomplish.
Another place to look for a bug: AXI does not guarantee read-after-write ordering. Check your ILA waveform to make certain that the write is truly getting done first.