将C-string转换为二进制值数组,然后逐位传输数组

时间:2016-12-07 08:48:25

标签: c arrays vhdl fpga avr

我想从AVR逐位向FPGA发送128位值。 FPGA期望发生以下事务:
1)RST信号清除FPGA的128位寄存器。走高,然后走低。 “CLOCK”信号设置为低 2)ENABLE位设置为高,表示正在进行传输 3)INPUT位设置为arrayOfBinaryValues [i]的值 4a)CLOCK信号变高。在前沿,INPUT的值存储在FPGA上的位置i 4b)CLOCK信号变低 4c)INPUT位设置为arrayOfBinaryValues [i]的下一个值 [重复4a-4c直到发送整个阵列]

所以,我写了一个函数来完成这个。它分阶段发生。步骤1,用户输入存储为c字符串的32个字符的值。由于这些是字符,我必须将它们转换为相应的十六进制值:

void transmitToFPGA(unsigned char hash[32]) {
    // convert the characters to their corresponding hex values
    unsigned char hash_hex[32];
    unsigned char j = 0;

    SET_BIT(FPGA_DDR,MD5_RST); // sets reset bit high

    for (unsigned char i=0; i<32; i++) {
        switch (hash[i]) {
            case '0': hash_hex[i] = 0x00; break;
            case '1': hash_hex[i] = 0x01; break;
            case '2': hash_hex[i] = 0x02; break;
            case '3': hash_hex[i] = 0x03; break;
            case '4': hash_hex[i] = 0x04; break;
            case '5': hash_hex[i] = 0x05; break;
            case '6': hash_hex[i] = 0x06; break;
            case '7': hash_hex[i] = 0x07; break;
            case '8': hash_hex[i] = 0x08; break;
            case '9': hash_hex[i] = 0x09; break;
            case 'A': hash_hex[i] = 0x0a; break;
            case 'B': hash_hex[i] = 0x0b; break;
            case 'C': hash_hex[i] = 0x0c; break;
            case 'D': hash_hex[i] = 0x0d; break;
            case 'E': hash_hex[i] = 0x0e; break;
            case 'F': hash_hex[i] = 0x0f; break;
            default:  hash_hex[i] = 0x00; break;
        }
    }

然后我尝试将相应的位转换为二进制值数组,如下所示:

   unsigned char hash_bin[128];
    for (unsigned char i=0; i<32; i++) {
        hash_bin[j] = hash_hex[i] & 0x01; j++;
        hash_bin[j] = hash_hex[i] & 0x02; j++;
        hash_bin[j] = hash_hex[i] & 0x04; j++;
        hash_bin[j] = hash_hex[i] & 0x08; j++;
    }

然后我执行传输

    // conduct transmission
    CLR_BIT(FPGA_DDR,MD5_RST);  // clear reset
    delay_ms(1);
    CLR_BIT(FPGA_DDR,AVR_CLK);         // AVR_CLK = 0
    delay_ms(1);
    CLR_BIT(FPGA_DDR,AVR_EN);          // AVR_EN = 0
    delay_ms(1);
    CLR_BIT(FPGA_DDR,AVR_IN);        // AVR_IN = 0
    delay_ms(1);
    for (unsigned char i=0; i<128; i++) {
        CLR_BIT(FPGA_DDR,AVR_CLK);     // AVR_CLK = 0
        delay_ms(1);
        SET_BIT(FPGA_DDR,AVR_EN);      // AVR_EN = 1
        delay_ms(1);
        if (hash_bin[i] == 0) {         // AVR_IN = hash_bin[i]
            CLR_BIT(FPGA_DDR,AVR_IN);
        } else {
            SET_BIT(FPGA_DDR,AVR_IN);
        }
        delay_ms(1);
  t      SET_BIT(FPGA_DDR,AVR_EN);      // AVR_CLK = 1
        delay_ms(1);
    }
}

不幸的是,这似乎不起作用,我不完全确定原因。我怀疑我执行转换的方式不正常。有没有人有任何见解?

编辑:这是此代码与之通信的VHDL模块:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SPI_Slave is
    Port ( AVR_IN   :   in      STD_LOGIC;
           AVR_CLK  :  in   STD_LOGIC;
           RST      :   in      STD_LOGIC;
              ENABLE        :   in  STD_LOGIC;
              READY         :   out     STD_LOGIC;
           HASH_OUT     :   out     STD_LOGIC_VECTOR (127 downto 0) := x"00000000000000000000000000000000" );
end SPI_Slave;

architecture Behavioral of SPI_Slave is

    shared variable count : integer := 0;
    signal hash : std_logic_vector(127 downto 0);   

begin

    PROCESS(AVR_CLK, ENABLE)
    BEGIN
        IF (ENABLE = '1') THEN                  -- If ENABLE is HIGH
            IF (rising_edge(AVR_CLK)) THEN  -- If CLK goes HIGH
                IF (RST = '1') THEN             -- If RST is HIGH
                    hash <= x"00000000000000000000000000000000"; -- then zero HASH_OUT and count
                    count := 0;
                    READY <= '0';               
                ELSE                                -- Otherwise, if RST is LOW
                    IF (count > 126) THEN
                        hash(count) <= AVR_IN;
                        HASH_OUT <= hash (127 downto 0);
                        READY <= '1';
                        count := count + 1;
                    ELSE 
                        hash(count) <= AVR_IN;
                        count := count + 1;
                        READY <= '0';
                    END IF;
                END IF;
            END IF;
        END IF;
    END PROCESS;





end Behavioral;

1 个答案:

答案 0 :(得分:1)

如果我是你,我会写这个函数,以便它以二进制为128位。

另外,我怀疑你的位设置不正确(截至写这个答案)。我试图在代码中的注释中解释我的逻辑:

#include <stdint.h>
#include <errno.h>

#define FPGA_LONG_DELAY() delay_ms(1)
#define FPGA_DELAY()      delay_ms(1)

int fpga_write_128bit(const uint8_t data[16])
{
    int i;

    if (!data)
        return EINVAL;

    /* Ensure non-active state. */
    CLR_BIT(FPGA_DDR, AVR_EN);
    CLR_BIT(FPGA_DDR, AVR_CLK);
    CLR_BIT(FPGA_DDR, MD5_RST);
    CLR_BIT(FPGA_DDR, AVR_IN);
    FPGA_LONG_DELAY();

    /* Prepare for reset on rising clock edge. */
    SET_BIT(FPGA_DDR, AVR_EN);
    SET_BIT(FPGA_DDR, MD5_RST);
    FPGA_DELAY();

    /* Pulse clock (rising and trailing edges). */
    SET_BIT(FPGA_DDR, AVR_CLK);
    FPGA_DELAY();
    CLR_BIT(FPGA_DDR, AVR_CLK);

    /* Set reset low, and prepare for sending the data bits. */
    CLR_BIT(FPGA_DDR, MD5_RST);

    for (i = 0; i < 128; i++) {

        /* AVR_CLK is low and AVR_EN high at this point. */

        /* Set data; LSB of first byte first. */
        if ((data[i / 8] & (1U << (i & 7))))
            SET_BIT(FPGA_DDR, AVR_IN);
        else
            CLR_BIT(FPGA_DDR, AVR_IN);

        /* Ensure data bit state is stable before rising edge of clock. */
        FPGA_DELAY();

        /* Clock pulse (both rising and trailing edges) */
        SET_BIT(FPGA_DDR, AVR_CLK);
        FPGA_DELAY();
        CLR_BIT(FPGA_DDR, AVR_CLK);
    }

    /* All bits transferred, clock is low. */

    CLR_BIT(FPGA_DDR, AVR_IN);   /* Irrelevant, but let's leave a known state behind */
    CLR_BIT(FPGA_DDR, AVR_EN);

    return 0;
}

您可能已经注意到我在那里使用了两个宏FPGA_LONG_DELAY()FPGA_DELAY()。正如现在定义的那样,发送一个128位的值需要259ms,或者超过四分之一秒。您可以将两者都定义为空字符串;如果没有,至少要短于1ms。

根据需要测试上述功能。

如果你仍然想要一个将128位字作为字符串的函数,只需创建一个解析十六进制值的包装函数,然后调用上面的函数。

上述函数首先发送第一个字节的最低有效位。如果我们将十六进制字符串视为单个128位数字,那么我们需要从右到左解析它,第一个(最右边)字符表示最低有效半字节(四位)。

如果您希望VHDL HASH_OUT状态为

HASH_OUT(   0 ) = 0
HASH_OUT(   1 ) = 0
HASH_OUT(   2 ) = 0
HASH_OUT(   3 ) = 0
HASH_OUT(   4 ) = 0
HASH_OUT(   5 ) = 0
HASH_OUT(   6 ) = 0
HASH_OUT(   7 ) = 0

HASH_OUT(   8 ) = 1
HASH_OUT(   9 ) = 0
HASH_OUT(  10 ) = 0
HASH_OUT(  11 ) = 0
HASH_OUT(  12 ) = 0
HASH_OUT(  13 ) = 0
HASH_OUT(  14 ) = 0
HASH_OUT(  15 ) = 0

HASH_OUT(  16 ) = 0
HASH_OUT(  17 ) = 1
HASH_OUT(  18 ) = 0
HASH_OUT(  19 ) = 0
HASH_OUT(  20 ) = 0
HASH_OUT(  21 ) = 0
HASH_OUT(  22 ) = 0
HASH_OUT(  23 ) = 0

HASH_OUT(  24 ) = 1
HASH_OUT(  25 ) = 1
HASH_OUT(  26 ) = 0
HASH_OUT(  27 ) = 0
HASH_OUT(  28 ) = 0
HASH_OUT(  29 ) = 0
HASH_OUT(  30 ) = 0
HASH_OUT(  31 ) = 0

依此类推,直到

HASH_OUT( 120 ) = 1
HASH_OUT( 121 ) = 1
HASH_OUT( 122 ) = 1
HASH_OUT( 123 ) = 1
HASH_OUT( 124 ) = 0
HASH_OUT( 125 ) = 0
HASH_OUT( 126 ) = 0
HASH_OUT( 127 ) = 0

您可以使用以下宏和data数组:

#define PACKBYTE(b0, b1, b2, b3, b4, b5, b6, b7) \
                (  (uint8_t)(!!(b0))       \
                | ((uint8_t)(!!(b1)) << 1) \
                | ((uint8_t)(!!(b2)) << 2) \
                | ((uint8_t)(!!(b3)) << 3) \
                | ((uint8_t)(!!(b4)) << 4) \
                | ((uint8_t)(!!(b5)) << 5) \
                | ((uint8_t)(!!(b6)) << 6) \
                | ((uint8_t)(!!(b7)) << 7) )

const uint8_t data[16] = {
     PACKBYTE( 0, 0, 0, 0, 0, 0, 0, 0 ),
     PACKBYTE( 1, 0, 0, 0, 0, 0, 0, 0 ),
     PACKBYTE( 0, 1, 0, 0, 0, 0, 0, 0 ),
     PACKBYTE( 1, 1, 0, 0, 0, 0, 0, 0 ),
     PACKBYTE( 0, 0, 1, 0, 0, 0, 0, 0 ),
     /* 10 PACKBYTE() lines omitted for brevity */
     PACKBYTE( 1, 1, 1, 1, 0, 0, 0, 0 )
};

请注意,宏中的!!只是两个非运算符。如果!!x为零,则x评估为0;如果x为非零,则评估为1。与通常情况不同,最左边的位是最不重要的,因此上面的数组的位数与VHDL中的HASH_OUT的位数相同。

对于十六进制字符串版本,我建议使用函数将字符转换为十进制:

static uint8_t hex_digit(const char c)
{
    switch (c) {
    case '0':           return  0U;
    case '1':           return  1U;
    case '2':           return  2U;
    case '3':           return  3U;
    case '4':           return  4U;
    case '5':           return  5U;
    case '6':           return  6U;
    case '7':           return  7U;
    case '8':           return  8U;
    case '9':           return  9U;
    case 'A': case 'a': return 10U;
    case 'B': case 'b': return 11U;
    case 'C': case 'c': return 12U;
    case 'D': case 'd': return 13U;
    case 'E': case 'e': return 14U;
    case 'F': case 'f': return 15U;
    default:            return 255U; /* Invalid value. */
    }
}

int fpga_write_hex_string(const char *const hex)
{
    uint8_t data[16], hi, lo;
    int     i;

    if (!hex)
        return EINVAL;

    for (i = 0; i < 16; i++) {

        /* Note: we parse the input string in pairs of
                 characters, leftmost first, so that if
                 it happens to be short, we won't try
                 to access it past its end. */

        hi = hex_digit(hex[2*i]);
        if (hi > 15U)
            return EINVAL;

        lo = hex_digit(hex[2*i + 1]);
        if (lo > 15U)
            return EINVAL;

        /* The i'th pair of hex digits form the
           (15-i)'th byte value. */
        data[15 - i] = lo | (hi << 4);
    }

    return fpga_write_128bit(data);
}

您当然可以接受二进制字符串(由01的128个字符组成,其顺序与VHDL HASH_OUT相同:

int fpga_write_bin_string(const char *const bin)
{
    uint8_t data[16] = {0};
    int     i;

    if (!bin)
        return EINVAL;

    for (i = 0; i < 128; i++)
        if (bin[i] == '1')
            data[i/8] |= 1U << (i & 7);
        else
        if (bin[i] != '0')
            return EINVAL;

    return fpga_write_128bit(data);
}

我希望我有一个这样的(带有FPGA的AVR或ARM)可以自己玩。所以,显然,上述所有代码都未经过测试。随意使用它(它在公共领域),但如果它打破你的董事会,不要怪我。