0
\$\begingroup\$

I connected my own FIFO to xillydemo. More precisely, xillydemo receives some data, it has to convert the data and the forward the data to FIFO. in turn the FIFO should send data back to xillydemo. What I want to do is to convert (in xillydemo.vhd) one every eight characters from upper case to lower case (and viceversa) and then send all of them to STD_FIFO. (E.g: input string in xillydemo.vhd is "HelloMyNameIsJohnAndIWorkInUK" then the string to be sent to STD_FIFO should be "helloMyNAmeIsJohNAndIWorKInUK").

To do this, I defined 4 signals wr_en, full, din and counter in xillydemo.vhd. wr_en, full and din are connected to user_w_write_8_wren, user_w_write_8_full and user_w_write_8_data xillydemosignals respectively. The counter is used to count from 0 to 7 in order to convert only the first char. The problem of my code is that it does not output anything. E.g., if the xillydemo input string is "HelloMyNameIsJohnAndIWorkInUK", the string sent back from STD_FIFO to xillydemo is empty.

NOTE: the problem is not similar to this question because the user suggested to go in this other question. The difference between this question and the two linked questions is that here I want to send to FIFO the swapped characters and not convert them into FIFO logic.

Here xillydmeo.vhd:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity xillydemo is
  port (
     PCIE_PERST_B_LS : IN std_logic;
     PCIE_REFCLK_N : IN std_logic;
     PCIE_REFCLK_P : IN std_logic;
     PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
     PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
     GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
     PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
     PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0));
end xillydemo;

architecture sample_arch of xillydemo is

  component xillybus
    port (
      PCIE_PERST_B_LS : IN std_logic;
      PCIE_REFCLK_N : IN std_logic;
      PCIE_REFCLK_P : IN std_logic;
      PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
      PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
      GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
      PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
      PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0);
      bus_clk : OUT std_logic;
      quiesce : OUT std_logic;

      user_r_read_8_rden : OUT std_logic;
      user_r_read_8_empty : IN std_logic;
      user_r_read_8_data : IN std_logic_vector(7 DOWNTO 0);
      user_r_read_8_eof : IN std_logic;
      user_r_read_8_open : OUT std_logic;
      user_w_write_8_wren : OUT std_logic;
      user_w_write_8_full : IN std_logic;
      user_w_write_8_data : OUT std_logic_vector(7 DOWNTO 0);
      user_w_write_8_open : OUT std_logic);
  end component;

  component STD_FIFO
    port (
      CLK: IN std_logic;
      RST: IN std_logic;
      DataIn: IN std_logic_VECTOR(7 downto 0);
      WriteEn: IN std_logic;
      ReadEn: IN std_logic;
      DataOut: OUT std_logic_VECTOR(7 downto 0);
      Full: OUT std_logic;
      Empty: OUT std_logic);
  end component;

  signal bus_clk :  std_logic;
  signal quiesce : std_logic;
  signal reset_8 : std_logic;

  signal user_r_read_8_rden  :  std_logic;
  signal user_r_read_8_empty :  std_logic;
  signal user_r_read_8_data  :  std_logic_vector(7 DOWNTO 0);
  signal user_r_read_8_eof   :  std_logic;
  signal user_r_read_8_open  :  std_logic;
  signal user_w_write_8_wren :  std_logic;
  signal user_w_write_8_full :  std_logic;
  signal user_w_write_8_data :  std_logic_vector(7 DOWNTO 0);
  signal user_w_write_8_open :  std_logic;

  signal wr_en               :  std_logic := '0';
  signal din                 :  std_logic_vector(user_w_write_8_data'range) := (others => '0');
  signal counter             :  integer := 0;
  signal full                :  std_logic := '0';
begin
  xillybus_ins : xillybus
    port map (
      -- Ports related to /dev/xillybus_read_8
      -- FPGA to CPU signals:
      user_r_read_8_rden => user_r_read_8_rden,
      user_r_read_8_empty => user_r_read_8_empty,
      user_r_read_8_data => user_r_read_8_data,
      user_r_read_8_eof => user_r_read_8_eof,
      user_r_read_8_open => user_r_read_8_open,

      -- Ports related to /dev/xillybus_write_8
      -- CPU to FPGA signals:
      user_w_write_8_wren => user_w_write_8_wren,
      user_w_write_8_full => user_w_write_8_full,
      user_w_write_8_data => user_w_write_8_data,
      user_w_write_8_open => user_w_write_8_open,

      -- General signals
      PCIE_PERST_B_LS => PCIE_PERST_B_LS,
      PCIE_REFCLK_N => PCIE_REFCLK_N,
      PCIE_REFCLK_P => PCIE_REFCLK_P,
      PCIE_RX_N => PCIE_RX_N,
      PCIE_RX_P => PCIE_RX_P,
      GPIO_LED => GPIO_LED,
      PCIE_TX_N => PCIE_TX_N,
      PCIE_TX_P => PCIE_TX_P,
      bus_clk => bus_clk,
      quiesce => quiesce
   );

  process (bus_clk)

  begin 
        if (bus_clk'event and bus_clk = '1') then
            if (reset_8 = '1') then 
                counter <= 0;
             else 
                wr_en <= user_w_write_8_wren;
                full <= user_w_write_8_full;

                if (user_w_write_8_wren='1') then
                    din <= user_w_write_8_data;

                    if counter=0 then
                        --From upper case to lower case
                        if (user_w_write_8_data="01000001") then --A
                            din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01000010") then --B
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01000011") then --C
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01000100") then --D
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01000101") then --E
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01000110") then --F
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01000111") then --G
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001000") then --H
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001001") then --I
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001010") then --J
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001011") then --K
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001100") then --L
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001101") then --M 
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001110") then --N 
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01001111") then --O
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010000") then --P
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010001") then --Q
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010010") then --R
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010011") then --S
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010100") then --T
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010101") then --U
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010110") then --V
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01010111") then --W
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01011000") then --X
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01011001") then --Y
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01011010") then --Z
                                      din(5) <= not user_w_write_8_data(5);

                                  --From lower case to upper case
                                  elsif (user_w_write_8_data="01100001") then --a
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01100010") then --b
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01100011") then --c
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01100100") then --d
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01100101") then --e
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01100110") then --f
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01100111") then --g
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101000") then --h
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101001") then --i
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101010") then --j
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101011") then --k
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101100") then --l
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101101") then --m
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101110") then --n
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01101111") then --o 
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110000") then --p 
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110001") then --q
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110010") then --r
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110011") then --s
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110100") then --t
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110101") then --u
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110110") then --v
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01110111") then --w
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01111000") then --x
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01111001") then --y
                                      din(5) <= not user_w_write_8_data(5);
                                  elsif (user_w_write_8_data="01111010") then --z
                                      din(5) <= not user_w_write_8_data(5);
                                  end if;
                              end if;

                              if (counter=7) then
                                  counter <= 0;
                              else
                                  counter <= counter+1;
                              end if; 
                          end if;
                      end if; 
                end if;
  end process;

  my_fifo : STD_FIFO
    port map(
          CLK       => bus_clk,
          RST       => reset_8,
          DataIn    => din,
          WriteEn   => wr_en,
          ReadEn    => user_r_read_8_rden,
          DataOut   => user_r_read_8_data,
          Full      => full,
          Empty     => user_r_read_8_empty
      );

    reset_8 <= not (user_w_write_8_open or user_r_read_8_open);
    user_r_read_8_eof <= user_r_read_8_empty and not(user_w_write_8_open);

end sample_arch;

Here FIFO code

library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

entity STD_FIFO is
    Generic (
        constant DATA_WIDTH  : positive := 8;
        constant FIFO_DEPTH : positive := 3
    );
    Port ( 
        CLK     : in  STD_LOGIC;
        RST     : in  STD_LOGIC;
        WriteEn : in  STD_LOGIC;
        DataIn  : in  STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
        ReadEn  : in  STD_LOGIC;
        DataOut : out STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
        Empty   : out STD_LOGIC;
        Full    : out STD_LOGIC
    );
end STD_FIFO;

architecture Behavioral of STD_FIFO is

begin

    -- Memory Pointer Process
    fifo_proc : process (CLK)
        type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
        variable Memory : FIFO_Memory;

        variable Head : natural range 0 to FIFO_DEPTH - 1;
        variable Tail : natural range 0 to FIFO_DEPTH - 1;

        variable Looped : boolean;
    begin
        if rising_edge(CLK) then
            if RST = '1' then
                Head := 0;
                Tail := 0;

                Looped := false;

                Full  <= '0';
                Empty <= '1';
            else
                if (ReadEn = '1') then
                    if ((Looped = true) or (Head /= Tail)) then
                        -- Update data output
                        DataOut <= Memory(Tail);

                        -- Update Tail pointer as needed
                        if (Tail = FIFO_DEPTH - 1) then
                            Tail := 0;

                            Looped := false;
                        else
                            Tail := Tail + 1;
                        end if;


                    end if;
                end if;

                if (WriteEn = '1') then
                    if ((Looped = false) or (Head /= Tail)) then
                        -- Write Data to Memory
                        Memory(Head) := DataIn;

                        -- Increment Head pointer as needed
                        if (Head = FIFO_DEPTH - 1) then
                            Head := 0;

                            Looped := true;
                        else
                            Head := Head + 1;
                        end if;
                    end if;
                end if;

                -- Update Empty and Full flags
                if (Head = Tail) then
                    if Looped then
                        Full <= '1';
                    else
                        Empty <= '1';
                    end if;
                else
                    Empty   <= '0';
                    Full    <= '0';
                end if;
            end if;
        end if;
    end process;

end Behavioral;
\$\endgroup\$
1
\$\begingroup\$

A simple solution would be to use a Mealy Machine. Here, you would only intercept the data user_w_write_8_data which will be written to the FIFO. All control signals associated with the write side should be left as in the original XillyBus demo. Thus, the instantiation of your STD_FIFO will be:

  my_fifo : STD_FIFO
    port map(
          CLK       => bus_clk,
          RST       => reset_8,
          DataIn    => din,                 -- modified data to write
          WriteEn   => user_w_write_8_wren, -- as in original demo!
          ReadEn    => user_r_read_8_rden,
          DataOut   => user_r_read_8_data,
          Full      => user_w_write_8_full, -- as in original demo!
          Empty     => user_r_read_8_empty
      );

Instead of STD_FIFO you can also use the component fifo_8x2048 of the XillyBus demo.

The Mealy Machine will then have a counter which is incremented with every write. Whenever the counter state is 0, the write data user_w_write_8_data is modified and assigned to signal din which is connected to the FIFO. In all other cases, the original value of user_w_write_8_data is assigned to din.

Thus, the code of the clocked process would look like this:

  process (bus_clk)
  begin 
        if (bus_clk'event and bus_clk = '1') then
            if (reset_8 = '1') then 
                counter <= 0;
             elsif (user_w_write_8_wren='1') then
                if counter = 7 then counter <= 0;
                else                counter <= counter + 1;
                end if;
             end if;
        end if;
  end process;

The Mealy Machine will have another process which defines the output for the current cycle based on the current state of the counter (or any other state variable). You must list all signals in any expression in the process sensitivity list. You must also assign a value to every output in every control path, otherwise you will get unintended latches. The latter is ensured by assigning a default value at the beginning of the process and overwrite it later on. Always the last assignment (before a wait) wins.

  process(counter, user_w_write_8_data)
  begin
     -- This is the default assignment which might be overriden below.
     din <= user_w_write_8_data;

     if counter=0 then
        --From upper case to lower case
        if (user_w_write_8_data="01000001") then --A
            din(5) <= not user_w_write_8_data(5);
        elsif (user_w_write_8_data="01000010") then --B
            --
            -- And so on
            --
        end if;
     end if;
  end process;
\$\endgroup\$
  • \$\begingroup\$ Great it works! I have a theoretical question. Why does not my code work? Well, the logic of my code is: if wr_en=1 then din<=wr_data. Then if counter=0 swap char, else do not swap. Everything was done in the same clock cycle. I don't understand why it does not work. \$\endgroup\$ – Message Passing Jan 11 '16 at 10:11
  • \$\begingroup\$ @MessagePassing Your code does not work, because your clocked process incurs a delay of one clock cycle for control signals wren and full. Thus, they do not match the XillyBus interface any more. That is the main difference between your solution and mine. \$\endgroup\$ – Martin Zabel Jan 11 '16 at 10:19
0
\$\begingroup\$

I don't have enough reputation to comment, but you need to be more specific on the problem.

  • Is it in simulation that your code does not work?
  • Which output is empty?
  • What is the input of the FIFO?
\$\endgroup\$
  • \$\begingroup\$ Hi. I put more details. With empty output I meant the string from FIFO to Xillybus. More precisely, xillybus converts the input string and send it to FIFO. In turn FIFO should send the converted string to xillybus but actually FIFO does not send anything. I tested the code on FPGA and it does not work \$\endgroup\$ – Message Passing Jan 10 '16 at 11:57
  • \$\begingroup\$ Hi. You should look at your code in simulation. It would also be very usefull to see what is the input into the FIFO \$\endgroup\$ – Rasmus B. Sorensen Jan 10 '16 at 12:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.