0

I have the following problem:

I have a PC which gives inputs to my SPARTAN 3AN FPGA and I wish to fetch those inputs, put them in a std_logic_vector, then convert them into integer. The instructions are divided in "n" instructions with 32 bits each. I need the first three bits be put in one integer, the next 28 in another, and the last is a "Last instruction flag". So, I have two arrays of 100 integers in which I would be putting the instructions (100 is the limit). If the "Last instruction flag" is one, than the entire operation should stop.

The program didn't synthesize properly, so I made a simulation of it. And I found the problem, but I don't know how to solve it, so I need your help. Here is the code and the simulation output:

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


entity BinaryDecimalConv is
end BinaryDecimalConv;

architecture Behavioral of BinaryDecimalConv is

    type int_array is array (100 downto 0) of integer;

    signal clkcnt: integer :=0;
    signal fbaud: integer;
    signal lastnumflag: std_logic:='0';
    signal clk: std_logic;
    signal PLCinput: std_logic;
    signal init: std_logic;
    signal BusyIN: std_logic;
    signal BusyOutSignal: std_logic;
    signal InnerBusyOut: std_logic;
    signal cnt: integer :=0;
    signal fbaut: integer :=0;
    signal pre_int: std_logic_vector (31 downto 0) := (others => '0');
    signal pre_spec_num: int_array := (others =>0);
    signal cylinder: int_array := (others => 0);
    signal InnerNumLength: integer:=0;
    signal num_length: integer:=0;

begin

CLOCKK: Process is
begin
    clk<='0';
    wait for 10 ns;
    clk<='1';
    wait for 10 ns;
end process CLOCKK;

fbaud <=5208;
BusyIN <='0';
init <='0';

PLC: Process is
    variable PrePLC: std_logic_vector(159 downto 0):="1010101010101010101010101001010010101010101010101010101010010100101010101010101010101010100101001010101010101010101010101001010010101010101010101010101010010101"; -- 1 with 100, 5 with 200, 5 2ith 200, 3 with 300, 4 with 750
begin
    PLCinput<=PrePLC(159);
    PrePLC:= PrePLC(158 downto 1) & '0';
    wait for 104166 ns;
end process;    


LastNum: process (LastNumFlag) is
    begin
    if LastNumFlag = '1' then
        BusyOutSignal <='1';
        InnerBusyOut <='1';
    else
        BusyOutSignal <='0';
        InnerBusyOut <='0';
    end if;
    end process LastNum;

DecoderAndAcquirer: process (PLCinput, BusyIN, InnerBusyOut,clk) is
begin

    if (clk'event and clk='1') then                                                         -- If rising edge on clock
        if ((BusyIN='0') and (InnerBusyOut='0') and (init='0')) then                        -- Check if FPGA and PLC are ready to exchange information and if init is done
            if (clkcnt = fbaud/2)                    then                                   --  If clkcnt is equal to half of the duration of the input bit then
                pre_int(31) <= PLCinput;                                                    -- Initialize the last digit of pre_int
                cnt <= cnt+1;                                                               -- Incrementing cnt => going towards bit 2
                clkcnt <=clkcnt+1;                                                          -- Incrementing clkcnt so you can exit this block
                if (cnt<32) then                                                            -- Checking if not last bit
                    pre_int <= '0' & pre_int(31 downto 1);                                  -- If not last bit, shift number to right
                else                                                                        -- else
                    cnt <=0;                                                                -- reset cnt to start with next instruction
                    if (pre_int(0)='1') then                                                -- Check if last digit is one
                        LastNumFlag <= '1';                                                 -- If last digit is one, stop acquiring instructions
                    else
                        LastNumFlag <='0';
                    end if;
                    pre_spec_num(InnerNumLength) <= to_integer(unsigned(pre_int(28 downto 1))); -- Conversion from binary to decimal for instruction
                    cylinder(InnerNumLength) <= to_integer(unsigned(pre_int(31 downto 29)));    -- Conversion from binary to decimal for the number of cylinder
                    InnerNumLength <= InnerNumLength +1;                                            -- Incrementing the number of instructions
                    num_length <= InnerNumLength;
                end if;
            elsif (clkcnt = fbaud) then                                                     -- If clkcnt has reached the entire length of the input bit
                clkcnt <= 0;                                                                -- set clkcnt to zero so the process can start from beginning.
            else                                                                            -- If clkcnt is less than or more than half of the entire duration, but surely
                clkcnt <= clkcnt +1;                                                        -- less than the entire duration, then increment the value of the clkcnt.
            end if;
        end if;
    end if;
end process DecoderAndAcquirer;

end Behavioral;

The thing is that, as shown on the picture, when cnt changes, nothing happens to the 31st bit of the instruction. Any ideas why?

Thanks, Bojan

Simulation

1 Answer 1

1

First PrePLC := PrePLC(158 downto 1) & '0'; mismatches length, so I assume this is to be PrePLC := PrePLC(158 downto 0) & '0'; instead, thus working as shift register.

In process DecoderAndAcquirer of the code there is:

...
pre_int(31) <= PLCinput;
...
if (cnt<32) then
  pre_int <= '0' & pre_int(31 downto 1);
...

So even through pre_int(31) is assigned, it is later overwritten in the pre_int <= '0' & pre_int(31 downto 1); since (cnt<32), whereby the pre_int(31) cant go high yet.

When simulating longer time, cnt goes to 32, and then the an '1' value is shown at pre_int(31); se figure below.

enter image description here

Edited: Below is version with temporary variable for pre_int, just to show the principles; operation is not verified.

DecoderAndAcquirer: process (PLCinput, BusyIN, InnerBusyOut,clk) is
  variable pre_int_v : std_logic_vector(pre_int'range);
begin

    if (clk'event and clk='1') then                                                         -- If rising edge on clock
        pre_int_v := pre_int;  -- Variable update from signal
        if ((BusyIN='0') and (InnerBusyOut='0') and (init='0')) then                        -- Check if FPGA and PLC are ready to exchange information and if init is done
            if (clkcnt = fbaud/2)                    then                                   --  If clkcnt is equal to half of the duration of the input bit then
                pre_int_v(31) := PLCinput;                                                    -- Initialize the last digit of pre_int
                cnt <= cnt+1;                                                               -- Incrementing cnt => going towards bit 2
                clkcnt <=clkcnt+1;                                                          -- Incrementing clkcnt so you can exit this block
                if (cnt<32) then                                                            -- Checking if not last bit
                    pre_int_v := '0' & pre_int_v(31 downto 1);                                  -- If not last bit, shift number to right
                else                                                                        -- else
                    cnt <=0;                                                                -- reset cnt to start with next instruction
                    if (pre_int_v(0)='1') then                                                -- Check if last digit is one
                        LastNumFlag <= '1';                                                 -- If last digit is one, stop acquiring instructions
                    else
                        LastNumFlag <='0';
                    end if;
                    pre_spec_num(InnerNumLength) <= to_integer(unsigned(pre_int_v(28 downto 1))); -- Conversion from binary to decimal for instruction
                    cylinder(InnerNumLength) <= to_integer(unsigned(pre_int_v(31 downto 29)));    -- Conversion from binary to decimal for the number of cylinder
                    InnerNumLength <= InnerNumLength +1;                                            -- Incrementing the number of instructions
                    num_length <= InnerNumLength;
                end if;
            elsif (clkcnt = fbaud) then                                                     -- If clkcnt has reached the entire length of the input bit
                clkcnt <= 0;                                                                -- set clkcnt to zero so the process can start from beginning.
            else                                                                            -- If clkcnt is less than or more than half of the entire duration, but surely
                clkcnt <= clkcnt +1;                                                        -- less than the entire duration, then increment the value of the clkcnt.
            end if;
        end if;
        pre_int <= pre_int_v;  -- Signals update from variable
    end if;
end process DecoderAndAcquirer;

Figure with waveform is shown below.

enter image description here

Sign up to request clarification or add additional context in comments.

7 Comments

Yes, for the first one, you are right. I've missed one bit (how come it does simulates it, though?). For the second: I do wish to overwrite it. Since, PLCinputs will be arriving every 104166 ns and I wish them to be shifted to the right, so even if it doesn't show it's value at the moment when it acquires a value, it should show preint(30) as a 1, because I actually did pre_int(30) <= pre_int(31) when I shifted it to the right. Let's say it's first iteration and i have 00000000000000000000000000000000, then, when PLCinput arrives, it becomes 10000000000000000000000000000000.
When I use pre_int <= '0' & pre_int(31 downto 1), I cut one zero from the end, making it 1000000000000000000000000000000, and adding zero in the front, making it 01000000000000000000000000000000. So this should appear on the plot. Shouldn't it?
For the first one: ModelSim reports error due to the length mismatch, so sounds like your simulator ain't picky enough. For the second: I have added figure that shows pre_int(31) as '1' after longer simulation, so cnt get to 32. For you last comment: No, the first pre_int(31) <= PLCinput; does not have any effect, since the signal assignment <= does not alter the signal value before next simulation cycle, so the subsequent pre_int <= '0' & pre_int(31 downto 1) will use the current value of pre_int, resulting in all 0's.
For the second: My simulator too shows one after 32 iterations, but that's not the behavior I am willing to get. I need it to change instantly, as soon as PLCinput gets a new value. In the original project (not the simulation one) i use variable for that cause, just because signals changes value after delta cycle. I used signals here because my simulator won't allow me to simulate variables, but at the point of writing the simulation project, I totally forgot about the signals and their assignment. But, my point is that I tried this even with variables. It still gives some weird number on exit
"So even through pre_int(31) is assigned, it is later overwritten in the pre_int <= '0' & pre_int(31 downto 1); since (cnt<32), whereby the pre_int(31) cant go high yet." There is no intervening passage of simulation time (no wait for, wait on, wait until). You have a current signal value and a next signal value. You traverse sequential statements before the delta cycle proceeds and update (overwrite) the next signal value, erasing the first write to pre_int(31).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.