Please help me with VHDL compile error [duplicate] - compilation

This question already has an answer here:
VHDL: Unable to read output status
(1 answer)
Closed 4 years ago.
library IEEE;
use IEEE.std_logic_1164.all;
entity doorlock is
port( reset : in std_logic;
enable : in std_logic;
password : in std_logic_vector (7 downto 0);
door : out std_logic_vector (7 downto 0);
lock : out std_logic;
alarm : out std_logic;
turnoff : out std_logic);
end doorlock;
--password is 10(decimal no.) which is 00010000(binary no.)
architecture DDL of doorlock is
signal err_count : integer range 0 to 5 := 0;
begin
lock <= '0' when (reset = '0');
alarm <= '0' when (reset = '0');
turnoff <= '0' when (reset = '0');
door <= "00000000" when (reset = '0');
lock <= '0' when (enable <= '0');
process(password)
begin
if (password = "-------1") then
door <= "00000000";
elsif (password = "------10") then
door <= "00000001";
elsif (password = "-----100") then
door <= "00000011";
elsif (password = "----1000") then
door <= "00000111";
elsif (password = "---00000") then
door <= "00001111";
elsif (password = "--110000") then
door <= "00011111";
elsif (password = "-1010000") then
door <= "00111111";
elsif (password = "10010000") then
door <= "01111111";
elsif (password = "00010000") then
door <= "11111111";
end if;
err_count <= err_count + 1;
end process;
alarm <= '1' when (err_count = 3);
turnoff <= '1' when (err_count = 5);
lock <= '1' when (door = "11111111" and turnoff = '0' and alarm = '0');
end DDL;
I made this code for my homework making digital door lock.
And this line have error as I compile it.
lock <= '1' when (door = "11111111" and turnoff = '0' and alarm = '0');
Error is like this below
** Error: D:\modelsim\Door.vhd(53): Cannot read output "alarm".
VHDL 2008 allows reading outputs.
This facility is enabled by compiling with -2008.
** Error: D:\modelsim\Door.vhd(53): Cannot read output "door".
VHDL 2008 allows reading outputs.
This facility is enabled by compiling with -2008.
** Error: D:\modelsim\Door.vhd(53): Cannot read output "turnoff".
VHDL 2008 allows reading outputs.
This facility is enabled by compiling with -2008.
** Error: D:\modelsim\Door.vhd(55): VHDL Compiler exiting
I don't know why it happens please help me

First off: "Please help me" is not a good question. Better would be something like "Modelsim error "cannot read output" when compiling"
Second off: The error is quite descriptive. "Cannot read output "alarm"". alarm is declared as
alarm : out std_logic;
Thus it is an output port. In pre-2008 VHDL it was not allowed to read output ports. Next the compiler hints on how to fix it:
"VHDL 2008 allows reading outputs. This facility is enabled by compiling with -2008."
So do so!
In your modelsim compilation window select "default options"
And then set to VHDL-2008
Alternatively you can actually do what is described (add the -2008) on the command line:
vcom -reportprogress 300 -work work -2008 doorlock.vhd
Voila. Finished! Not?
No wait, still doesn't work!
You have a multiple driver error. In line 23 it states:
door <= "00000000" when (reset = '0');
This acts as a latch, effectively being the same as
process(reset) begin
if reset = '0' then
door <= "00000000";
end if;
end process;
Thus once reset='0' has occurred, the process will drive door to a fixed value. In the password-triggered process you again drive door! This will resolve badly. E.g. if (password = "------10"), then door <= "00000001". This will resolve:
resolve("00000000", "00000001") = "0000000X"
Because connecting '0' to '1' is equivalently a short-circuit.
So let's look at proper design. You're now triggering on a change of password. Not so nice, but it's possible. I would use another trigger, like the enable signal that is not being used. But anyhow: we introduce an extra signal to detect the change password_delay. But more importantly we introduce a clock. In digital hardware most systems use a clock. Finally, we use the new VHDL-2008 statement case? to decode the don't cares.
Together the VHDL-2008 code becomes:
library IEEE;
use IEEE.std_logic_1164.all;
entity doorlock is
port(
clk : in std_logic;
reset : in std_logic;
enable : in std_logic;
password : in std_logic_vector (7 downto 0);
door : out std_logic_vector (7 downto 0);
lock : out std_logic;
alarm : out std_logic;
turnoff : out std_logic
);
end doorlock;
--password is 10(decimal no.) which is 00010000(binary no.)
architecture DDL of doorlock is
signal password_delay : std_logic_vector(password'range) := password;
use ieee.numeric_std_unsigned.all;
signal err_count : integer range 0 to 5 := 0;
begin
clk_proc : process(clk) begin
if rising_edge(clk) then
if reset = '0' then
door <= (others => '0');
lock <= '0';
alarm <= '0';
turnoff <= '0';
err_count <= 0;
else -- no reset :)
if password /= password_delay then
case? password is
when "-------1" => door <= "00000000";
when "------10" => door <= "00000001";
when "-----100" => door <= "00000011";
when "----1000" => door <= "00000111";
when "---00000" => door <= "00001111";
when "--110000" => door <= "00011111";
when "-1010000" => door <= "00111111";
when "10010000" => door <= "01111111";
when "00010000" => door <= "11111111";
when others => null;
end case?;
err_count <= err_count + 1;
end if;
case err_count is
when 3 => alarm <= '1';
when 5 => turnoff <= '1';
when others => null;
end case;
if door = "11111111" and turnoff = '0' and alarm = '0' then
lock <= '1';
end if;
end if;
password_delay <= password;
end if;
end process;
end DDL;
That's something different, eh? I'm sorry, but I don't have time to write a test bench for you.
NOTE: The code gives a compiler warning
Warning: C:/HDL/doorlock/doorlock.vhd(20): (vcom-1013) Initial value of "password_delay" depends on value of signal "password".
Ignore this. This is required for simulation as else undefined initial value of password_delaywill cause a trigger of password /= password_delay.

Related

In behavioral simulation, my FSM have a state that take more than 1 clock cycle ... And i don't like it

Please forgive myself if you will find some trivial errors in my code .. I'm still a beginner with VHDL.
Well, I have to deal with a serial interface from an ADC. The interface is quite simple ... there is a wire for the serial data (a frame of 24 bits), a signal DRDY that tells me when the new sample data is available and a serial clock (SCLK) that push the bit into (rising edge). Everything is running continuously...
I need to capture correctly the 24 bit of the sample, put them on a parallel bus (shift register) and provide a "data valid" signal for the blocks that will process the samples ...
Due to the fact that my system clock is x4 the frequency of the serial interface, i was thinking that doing the job with a FSM will be easy ...
When you look into the code you will see a process to capture the rising edges of the DRDY and SCLK.
Then a FSM with few states (Init, wait_drdy, wait_sclk, inc_count, check_count).
I use a counter (cnt unsigned) to check if I've already captured the 24 bits, using also to redirect the states of the FSM in "check_count" state.
Here a picture:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity serial_ads1675 is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
sclk : in std_logic;
sdata : in std_logic;
drdy : in std_logic;
pdata : out std_logic_vector(23 downto 0);
pdready : out std_logic
);
end serial_ads1675;
architecture Behavioral of serial_ads1675 is
-- Internal declarations
signal ipdata : std_logic_vector (23 downto 0);
signal ipdready : std_logic;
signal tmp1, tmp2, tmp3, tmp4 : std_logic;
signal rise_drdy, rise_sclk : std_logic;
signal cnt : unsigned (4 downto 0);
type state is (init, wait_drdy, wait_sclk, inc_count, check_count);
signal actual_state, next_state : state;
begin
-- Concurrent statements
pdata <= ipdata;
pdready <= ipdready;
rise_drdy <= '1' when ((tmp1 = '1') and (tmp2 = '0')) else '0';
rise_sclk <= '1' when ((tmp3 = '1') and (tmp4 = '0')) else '0';
-- Process
process (clk, reset)
begin
if(reset = '0') then
tmp1 <= '0';
tmp2 <= '0';
tmp3 <= '0';
tmp4 <= '0';
elsif (falling_edge(clk)) then
tmp1 <= drdy;
tmp2 <= tmp1;
tmp3 <= sclk;
tmp4 <= tmp3;
end if;
end process;
process (reset, clk)
begin
if (reset = '0') then
actual_state <= init;
elsif (rising_edge(clk)) then
actual_state <= next_state;
end if;
end process;
process (rise_sclk, rise_drdy) -- Next State affectation
begin
case actual_state is
when init =>
next_state <= wait_drdy;
ipdata <= (others => '0');
ipdready <= '0';
cnt <= (others => '0');
when wait_drdy =>
if (rise_drdy = '0') then
next_state <= actual_state;
else
next_state <= wait_sclk;
end if;
cnt <= (others => '0');
when wait_sclk =>
if (rise_sclk = '0') then
next_state <= actual_state;
else
next_state <= inc_count;
end if;
ipdready <= '0';
when inc_count =>
next_state <= check_count;
cnt <= cnt + 1;
ipdready <= '0';
ipdata(23 downto 1) <= ipdata(22 downto 0);
ipdata(0) <= sdata;
when check_count =>
case cnt is
when "11000" =>
next_state <= wait_drdy;
ipdready <= '1';
when others =>
next_state <= wait_sclk;
ipdready <= '0';
end case;
when others =>
next_state <= init;
end case;
end process;
end Behavioral;
My problem is during the check_count state ...
I'm expecting that this state should last one system clock cycle, but actually it last much more.
Here a snapshot of the behavioral simulation:
Due to the fact that this state last more than expected, i miss the following SCLK pulse and don't record the next bit ...
I don't understand why this state last so many system clock cycles instead of just one ...
Anyone has some clues and bring some light in my dark night ?
Thanks in advance.
Edit: I've tried to change the signal cnt for an integer variable internal to the process of the FSM ... Same results
The error is this:
process (rise_sclk, rise_drdy) -- Next State affectation
begin
-- code omitted, but does generally this:
next_state <= SOME_VALUE;
end process;
Because the sensitivity list includes only the signals rise_sclk and rise_drdy, the process is "executed" only if any of these signals changes. You can follow this in the wave diagram.
You don't have a synchronous design running on clk. Put clk on the sensitivity list and base the decisions on the levels of rise_sclk and rise_drdy. As an excerpt:
process (clk) -- Next State affectation
begin
if rising_edge(clk) then
case actual_state is
when init =>
next_state <= wait_drdy;
-- and so on
end case;
end if;
end process;

VHDL wrapper for 1-wire core for DS18B20 temperature sensor

currently I am trying to write a VHDL wrapper for this Opencore Verilog module (1-wire master) so that I can send/receive from this temperature sensor (DS18B20).
However I am struggling to understand the usage. Namely the read/write enable vs. the cyc bit in the control/status register of the 1-wire master module.
The code I have so far sets the cyc bit to 1 and the read/write enable to one simultaneously but does not cycle them during each bit. Is this correct or am I misunderstanding it? I'm new to VHDL/ reading a datasheet so I have been struggling over this for a few days. Any help would be appreciated.
I found this site that I have been using as a reference but it does not deal with the Verilog module that I am using.
I am also looking for tips on my code style, and VHDL tips in general.
My current code:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; --may need to remove if signed not used
ENTITY one_wire_temp_probe_control IS
GENERIC (
one_us_divider_g : integer range 0 to 50 := 50 -- clock divider for one micro second
);
PORT (
i_clk_50mhz : IN STD_LOGIC;
i_read_enable : IN std_logic;
io_temp_probe : INOUT STD_LOGIC; --how do i register an inout
o_temperature : OUT signed(6 DOWNTO 0);
o_temp_ready : OUT std_logic
);
END one_wire_temp_probe_control;
ARCHITECTURE rtl of one_wire_temp_probe_control IS
----temp commands----
CONSTANT skip_rom_c : std_logic_vector(7 DOWNTO 0) := x"CC"; --command to skip ROM identity of temperature sensor
CONSTANT convert_temp_c : std_logic_vector(7 DOWNTO 0) := x"44"; --command to start temperature conversion
CONSTANT read_scratchpad_c : std_logic_vector(7 DOWNTO 0) := x"BE"; --command to read the scratchpad i.e. get temperature data
CONSTANT command_bits_c : integer RANGE 0 TO 8 := 8; --number of bits in the above commands (note: range used to limit number of bits to minimum needed)
CONSTANT data_bits_c : integer RANGE 0 to 12 := 12; --number of bits in received data
----1-wire commands----
CONSTANT send_reset_pulse : std_logic_vector(7 DOWNTO 0) := "00001010"; --command to send reset pulse
CONSTANT write_command_structure_c : std_logic_vector(6 DOWNTO 0) := "0000000"; --structure of the command that must be passed to the 1-wire controller (----EDIT----)
----timing constants----
CONSTANT delay_65us_c : integer := one_us_divider_g * 65; --65 micro-second delay
CONSTANT delay_960us_c : integer := one_us_divider_g * 960; --960 micro-second delay
CONSTANT delay_750ms : integer := one_us_divider_g * 1000 * 750; --760 milli-second delay
----state machine----
TYPE state_type IS (idle, presence_pulse, wait_presence_pulse, skip_rom, temp_conversion, wait_for_conversion,
read_scratchpad, data_read, convert_data, wait_65us);
SIGNAL state : state_type := idle;
SIGNAL previous_state : state_type := idle;
----1-wire----
SIGNAL read_enable_s, write_enable_s, reset_s, owr_e_s : std_logic := '0';
SIGNAL write_data_s, read_data_s : std_logic_vector(7 DOWNTO 0):= (OTHERS => '0'); --8 bit mode chosen in sockit_owm
SIGNAL address_s : std_logic_vector(1 DOWNTO 0) := "00";
SIGNAL timer_s : integer := 0;
----commands---
SIGNAL bit_counter_command_s : integer RANGE 0 TO command_bits_c := 0; --counter for bits in commands (note: not -1 due to using 9th bit as state change)
SIGNAL bit_counter_data_s : integer RANGE 0 TO data_bits_c := 0; --counter for bits in data recieved
----temperature----
SIGNAL temperature_raw_data : std_logic_vector(11 DOWNTO 0) := (OTHERS => '0');
----one wire control----
COMPONENT sockit_owm IS
PORT (
----control interface----
clk : IN std_logic;
rst : IN std_logic;
bus_ren : IN std_logic;
bus_wen : IN std_logic;
bus_adr : IN std_logic_vector(7 DOWNTO 0);
bus_wdt : IN std_logic_vector(7 DOWNTO 0);
bus_rdt : OUT std_logic_vector(7 DOWNTO 0);
bus_irq : OUT std_logic;
----1-wire interface----
owr_p : OUT std_logic; --verilog code is a one bit wide vector
owr_e : OUT std_logic;
owr_i : IN std_logic
);
END COMPONENT;
BEGIN
address_s <= "00"; --for the temp probe control we're not interested in other address spaces
PROCESS(i_clk_50mhz) BEGIN --state change
IF rising_edge(i_clk_50mhz) THEN
CASE state is
WHEN idle =>
o_temp_ready <= '0';
IF (i_read_enable = '1') THEN
state <= presence_pulse;
ELSE
state <= idle;
END IF;
WHEN presence_pulse =>
----send reset/presence pulse----
write_enable_s <= '1';
write_data_s <= send_reset_pulse;
timer_s <= delay_960us_c;
state <= wait_presence_pulse;
WHEN wait_presence_pulse =>
----wait for 960 micro seconds----
read_enable_s <= '1';
IF (timer_s = 0) THEN
IF (read_data_s(0) = '0') THEN
state <= skip_rom;
ELSIF (read_data_s(0) = '1') THEN
--precence not detected
ELSE
state <= wait_presence_pulse;
END IF;
ELSE
timer_s <= timer_s - 1;
state <= wait_presence_pulse;
END IF;
WHEN skip_rom =>
----send skip rom command----
previous_state <= skip_rom;
write_enable_s <= '1';
IF (bit_counter_command_s = command_bits_c) THEN
bit_counter_command_s <= 0;
state <= temp_conversion;
ELSE
write_data_s <= write_command_structure_c & skip_rom_c(bit_counter_command_s); ---command structure concatonated with 1 bit from command
bit_counter_command_s <= bit_counter_command_s + 1;
timer_s <= delay_65us_c;
state <= wait_65us;
END IF;
WHEN temp_conversion =>
----send temp conversion command to probe----
previous_state <= temp_conversion;
IF (bit_counter_command_s = bit_counter_command_s) THEN
bit_counter_command_s <= 0;
timer_s <= delay_750ms;
state <= wait_for_conversion;
ELSE
write_data_s <= write_command_structure_c & convert_temp_c(bit_counter_command_s); ---command structure concatonated with 1 bit from command
bit_counter_command_s <= bit_counter_command_s + 1;
timer_s <= delay_65us_c;
state <= wait_65us;
END IF;
WHEN wait_for_conversion =>
----wait for temperature conversion to finish----
IF (timer_s = 0) then
state <= read_scratchpad;
ELSE
timer_s <= timer_s - 1;
END IF;
WHEN read_scratchpad =>
----send read scratchpad command----
previous_state <= read_scratchpad;
IF (bit_counter_command_s = command_bits_c) THEN
state <= data_read;
bit_counter_command_s <= 0;
ELSE
write_data_s <= write_command_structure_c & read_scratchpad_c(bit_counter_command_s); ---command structure concatonated with 1 bit from command
bit_counter_command_s <= bit_counter_command_s + 1;
timer_s <= delay_65us_c;
state <= wait_65us;
END IF;
WHEN data_read =>
----read incoming data----
previous_state <= data_read;
read_enable_s <= '1';
IF (bit_counter_data_s = data_bits_c) THEN
bit_counter_data_s <= 0; --may need to invert this
state <= convert_data;
ELSE
temperature_raw_data(bit_counter_data_s) <= read_data_s(0);
bit_counter_data_s <= bit_counter_data_s + 1;
timer_s <= delay_65us_c;
state <= wait_65us;
END IF;
WHEN convert_data =>
----convert raw data into temperature----
o_temp_ready <= '1';
WHEN wait_65us =>
----wait for read/write cycle to finish----
IF (timer_s = 0) THEN
state <= previous_state;
ELSE
timer_s <= timer_s - 1;
state <= wait_65us;
END IF;
END CASE;
END IF;
END PROCESS;
----one wire component instantiation----
one_wire_control : sockit_owm
PORT MAP(
----control interface----
clk => i_clk_50mhz,
rst => reset_s,
bus_ren => read_enable_s,
bus_wen => write_enable_s,
bus_adr => address_s,
bus_wdt => write_data_s,
bus_rdt => read_data_s,
bus_irq => OPEN,
----1-wire interface----
owr_p => OPEN,
owr_e => owr_e_s,
owr_i => io_temp_probe
);
io_temp_probe <= owr_e_s ? '0' : 'Z'; --I also need help converting this line to VHDL
END rtl;
Thank you in advance.
Best
Tom
I am also looking for tips on my code style, and VHDL tips in general.
OK.
First thing: don't make the lines so long. So don't put comments at the end of a line. Put them a line before.
use IEEE.NUMERIC_STD.ALL; --may need to remove if signed not used
then remove, as I don't see any signed
one_us_divider_g : integer range 0 to 50 := 50 -- clock divider for one micro second
So... what happens is one_us_divider_g is set to 0? Seems an illegal value. Using it for simulation?
io_temp_probe : INOUT STD_LOGIC; --how do i register an inout
One option is to use a tristate IOBUFFER. This is a special FPGA edge element which splits the input and output to separate signals. You can tristate the ouput by setting a control port.
Alternatively you could just do it the way you do in your code (this is also explained in for instance the Xilinx synthesis user guide). Which leads me to another question in your code.
io_temp_probe <= owr_e_s ? '0' : 'Z'; --I also need help converting this line to VHDL
io_temp_probe <= '0' when owr_e_s = '1' else 'Z';
CONSTANT command_bits_c : integer RANGE 0 TO 8 := 8;
No need for an integer range if it is a constant.
CONSTANT send_reset_pulse : ...
CONSTANT delay_750ms : ...
Missing the "_c" you put behind all your constants. But I would not add this "s", "_c" or "_g" anyhow. A lot of work for little gain.
COMPONENT sockit_owm IS
PORT (
[...]
);
END COMPONENT;
Component declarations are not required anymore since some time now. You can remove it and change your instantiation:
one_wire_control : entity work.sockit_owm
PORT MAP(
[...]
WHEN idle =>
[...]
ELSE
state <= idle;
END IF;
not required. If you don't change state, it stays at idle.
WHEN wait_presence_pulse =>
IF (timer_s = 0) THEN
IF (read_data_s(0) = '0') THEN
[...]
ELSIF (read_data_s(0) = '1') THEN
[...]
ELSE
state <= wait_presence_pulse;
END IF;
read_data_s(0) '0' and '1' are covered. Do you expect any other value? That can only happen in simulation, not in implementation. So the code in the last else-statement is unreachable then.
[...]
timer_s <= delay_65us_c;
state <= wait_65us;
[...]
WHEN wait_65us =>
IF (timer_s = 0) THEN
[...]
ELSE
timer_s <= timer_s - 1;
END IF;
Let's say a delay is 65 us lasts 10 clock cycles. Setting the divider to 1, delay_65us_c=10. So at t=0, timer_s is set to 10. at t=1 -state is wait_65us now- timer_s is set to 9. And so on: at t=10, timer_s is set to 0... but state is still wait_65us. So at t=11, timer_s is detected 0, and state is changed to the previous one. Which it will enter at t=12.
So, instead of a 10 clock cycle delay, you get a 12 clock cycle delay.
Is this a problem? If yes, you should reconsider your code.
SIGNAL read_enable_s, write_enable_s, reset_s, owr_e_s : std_logic := '0';
[... not used anywhere else... ]
one_wire_control : sockit_owm
PORT MAP(
[...]
rst => reset_s,
Are you sure this is correct? A lot of components need to be properly reset before they operate correctly.
If you're working with Quartus, you can mix VHDL code with Verilog and even schematic elements. In the link below, I use a verilog driver for the same chip (DS18B20).
See here for details:
https://physnoct.wordpress.com/2016/12/14/altera-quartus-combining-verilog-and-vhdl/

VHDL uart which send 16 chars string

I have to do UART with vhdl on the Xilinx which will send 16 chars string. I wrote such code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(3 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(9 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
-- freq of clock
begin
process(CLK, RESET)
begin
if rising_edge(CLK) then
if(A = '1' and K < 10416) then
K <= K + 1;
CLK_Txd <= K(13);
elsif(B = '1' and K < 5208) then
K <= K + 1;
CLK_Txd <= K(12);
elsif(C = '1' and K < 20832) then
K <= K + 1;
CLK_Txd <= K(14);
else
K <= (others => '0');
end if;
end if;
end process;
--counter
process(CLK_Txd, RESET, ENABLE)
begin
if(RESET = '1' and ENABLE = '0') then
Q <= "0000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
--comparator
ENABLE <= '1' when (Q > 4) else '0';
--transcoder
process(Q, CLK_Txd)
begin
if (rising_edge(CLK_Txd)) then
case Q is
when "0001" => DATA <= x"40";
when "0010" => DATA <= x"41";
when "0011" => DATA <= x"42";
when "0100" => DATA <= x"43";
when "0101" => DATA <= x"44";
when "0110" => DATA <= x"45";
when "0111" => DATA <= x"46";
when "1000" => DATA <= x"47";
when "1001" => DATA <= x"48";
when "1010" => DATA <= x"49";
when "1011" => DATA <= x"50";
when "1100" => DATA <= x"51";
when "1101" => DATA <= x"52";
when "1110" => DATA <= x"53";
when "1111" => DATA <= x"54";
when others => DATA <= x"55";
end case;
end if;
end process;
--uart
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '0') then
QTxD <= DATA & "01";
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(9 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
It's send data completely not connected with that what i have in transcoder and realy dont know why. Do you have any ideas what is wrong with my code, or do you have any diffrent examples of it how to send your own 16 chars with uart? I suppose that something is wrong with my counter or comparator.
--EDIT
Thans for your effort, i can't try your code at the Xilinx right now couse I am workin on it at my university. I see that you made a lot of changes in my code. Of course first i try to do it like you show and i hope this will be acceptable, but I propably have to do it with transcoder according to this picture.
From last time i made such changes i my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(7 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(7 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
signal QPrim: std_logic_vector(3 downto 0);
begin
process(CLK, RESET)
begin
CLK_Txd <= CLK;
end process;
process(CLK_Txd, RESET, ENABLE)
begin
if(ENABLE = '0') then
Q <= "00000000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
ENABLE <= '1' when (Q <= 255) else '0';
process(Q(7 downto 4))
begin
case Q(7 downto 4) is
when "0000" => DATA <= x"40";
when "0001" => DATA <= x"41";
when "0010" => DATA <= x"42";
when "0011" => DATA <= x"43";
when "0100" => DATA <= x"44";
when "0101" => DATA <= x"45";
when "0110" => DATA <= x"46";
when "0111" => DATA <= x"47";
when "1000" => DATA <= x"48";
when "1001" => DATA <= x"49";
when "1010" => DATA <= x"50";
when "1011" => DATA <= x"51";
when "1100" => DATA <= x"52";
when "1101" => DATA <= x"53";
when "1110" => DATA <= x"54";
when "1111" => DATA <= x"55";
when others => DATA <= x"56";
end case;
end process;
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '1') then
QTxD <= DATA;
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(7 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
According to that i send MSB to transcoder and LSB to comparator but my program all the time still send x"40" to DATA and it is propably connected with this counter which you were talking about.
There is my simulation efect. I becoming upset with that couse i don't have enough skills in vhdl to do it by my self. I hope that you will help me to do rebuild my project. On simulation it looks good i dont know how it looks on Xilinx.
Can you show me a piece of code? - Stefan
The entire purpose to providing the link to Adrian Adamcyzk's code (Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART) was to provide an example with a bit (baud) counter and flip flop used to control sending the message once.
Here's Jackob's modified:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity uartbyjackob is
port (
clk, a, b, c: in std_logic;
reset: in std_logic;
txd, txdosc: out std_logic
);
end entity uartbyjackob;
architecture foo of uartbyjackob is
-- signal k: unsigned(14 downto 0); -- FOR simulation
-- note if k were used in simulation it would require initialization
signal q: unsigned (3 downto 0); -- WAS std_logic_vector
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(9 downto 0);
-- signal data: std_logic_vector(7 downto 0);
-- added:
signal bdcnt: unsigned (3 downto 0);
signal ldqtxd: std_logic;
signal davl: std_logic;
type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
constant data: data_lut := (
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
);
signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk) then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
clk_txd <= clk; -- SHORTENS SIMULATION
DAVL_FF: -- DATA_AVAILABLE to send
process (clk_txd, reset)
begin
if reset = '1' then
davl <= '0';
elsif rising_edge (clk_txd) then
if q = 15 and bdcnt = 9 then -- a JK FF equivalent
davl <= '0';
elsif q = 0 then
davl <= '1'; -- one clock holderover from reset
-- else
-- davl <= davl;
end if;
end if;
end process;
-- process(clk_txd, reset, enable)
-- begin
-- if reset = '1' and enable = '0' then
-- q <= "0000";
-- elsif rising_edge(clk_txd) then
-- q <= q + 1;
-- end if;
-- end process;
QCNT:
process (clk_txd, reset)
begin
if reset = '1' then
q <= (others => '0');
elsif rising_edge (clk_txd) then
if enable = '1' then
q <= q + 1;
end if;
end if;
end process;
BAUD_COUNTER:
process (clk_txd, reset)
begin
if reset = '1' then
bdcnt <= (others => '0');
elsif rising_edge (clk_txd) then
if davl = '0' or bdcnt = 9 then
bdcnt <= (others => '0');
else
bdcnt <= bdcnt + 1;
end if;
end if;
end process;
-- comparator
-- enable <= '1' when (q > 4) else '0';
enable <= '1' when bdcnt = 9 and davl = '1' and q /= 15 else
'0';
-- q latches at 15;
ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
'0';
datalut <= data(to_integer(q)); -- FOR SIMULATION VISIBILITIY
--transcoder
-- process(q, clk_txd)
-- begin
-- if rising_edge(clk_txd) then
-- case q is
-- when "0001" => data <= x"40";
-- when "0010" => data <= x"41";
-- when "0011" => data <= x"42";
-- when "0100" => data <= x"43";
-- when "0101" => data <= x"44";
-- when "0110" => data <= x"45";
-- when "0111" => data <= x"46";
-- when "1000" => data <= x"47";
-- when "1001" => data <= x"48";
-- when "1010" => data <= x"49";
-- when "1011" => data <= x"50";
-- when "1100" => data <= x"51";
-- when "1101" => data <= x"52";
-- when "1110" => data <= x"53";
-- when "1111" => data <= x"54";
-- when others => data <= x"55";
-- end case;
-- end if;
-- end process;
-- uart
-- process (clk_txd, enable, data)
-- begin
-- if enable = '0' then
-- qtxd <= data & "01";
-- elsif rising_edge(clk_txd) then
-- qtxd <= '1' & qtxd(9 downto 1);
-- end if;
-- end process;
TX_SHIFT_REG:
process (clk_txd, reset) -- shift regiseter Tx UART
begin
if reset = '1' then
qtxd <= (others => '1'); -- output mark by default
elsif rising_edge (clk_txd) then
if ldqtxd = '1' then
qtxd <= '1' & data(to_integer(q)) & '0';
-- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
else
qtxd <= '1' & qtxd(9 downto 1); -- shift out;
end if;
end if;
end process;
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity uartbyjackob_tb is
end entity;
architecture foo of uartbyjackob_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal txd: std_logic;
begin
DUT:
entity work.uartbyjackob
port map (
clk => clk, -- clk_txd driven by clk
a => 'X',
b => 'X',
c => 'X', -- a, b, c aren't used
reset => reset,
txd => txd,
txdosc => open
);
CLOCK:
process
begin
wait for 52.35 us;
clk <= not clk;
if now > 20000 us then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 104.7 us;
reset <= '1';
wait for 104.7 us;
reset <= '0';
wait;
end process;
end architecture;
The model has been modified for faster simulation, ignoring the baud rate clock generator.
There's an added flip flop (davl) for enabling the UART to run. There's an added baud (bit) counter bdcnt.
I changed the order of the start, stop and data values loaded into QTxD so the start bit came out first, followed by 8 data bits and the stop bit.
You can read off TxD from left to right start bit, data(q)(0) ... data(q(7), stop bit. The enable or ldqtxd will occur at the same time as a stop bit.
There's only one observable draw back to this implementation, if you reset while a value in the shift register hasn't finished loading you'll cause a framing error for the receiver. Don't reset it for 10 baud times after davl goes false.
The simulation is shown with a 9600 baud clk_txd, the characters go out back to back.
It has fewer flip flops than the original (disregarding k). There is no data register separate from QTxD ( - 8 FFs) plus bdcnt (+ 4) plus davl (+ 1). There are two comparisons (optimized to two) bdcnt = 9, q =, /= 9. Those could be expressed separately so it doesn't require optimization during synthesis.
I changed the look up table style, a matter of personal preference also the excuse for changing counters to type unsigned and using only package numeric_std for arithmetic.
The little testbench likewise doesn't expect the k counter to generate the baud clock.
Running the testbench gives:
Where there's an added signal datalut to show the value being shifted out after ldqtxd.
After your change making the q counter (7 downto 0)
We still see from your waveform that it doesn't work.
This is due to the enable and the shift register.
If you use a single counter with the upper four bits indexing the output character your character is transmitted in 10 out of the 16 clk_txd times indexed by the lower four bits of the counter. The remaining clock times TxD should be '1' (idle line marks in RS-232 parlance).
The order for data to be transmitted will be a space (the start bit), data(0) through data(7) and a mark (the stop bit). (Shown left to right on TxD).
For simulation the k counter is not used. I included it commented out below.
I made several changes for proper simulation. These include synchronously loading the shift register containing QTxD, synchronously clearing the rightmost bit of QTxD to provide a full width and moving enable to occur once every sixteen clocks (clk_txd). The enable is preceded by a new clear for the start bit and both been offset to prevent it from occurring during reset which has the effect of causing a framing error on the first character for any receiver.
Simulation is done with the same testbench I provide above.
The changes to your new code are shown by comments:
architecture behavioral of uartbyjackob is
-- signal k: std_logic_vector(14 downto 0);
signal q: unsigned (7 downto 0); -- std_logic_vector(7 downto 0);
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(7 downto 0);
-- using an 8 bit shift register requires a method of outputting a
-- synchronous start bit (the width is important for receive framing)
-- and synchronous stop bit
signal data: std_logic_vector(7 downto 0);
signal qprim: std_logic_vector(3 downto 0);
signal clear: std_logic; -- synchronous clear for start bit
begin
-- let's keep this here for when you put it the FPGA
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
process (clk) -- , reset)
begin
clk_txd <= clk; -- if simply a concurrent assignment statement this
end process; -- would look similar to the elaborated equivalent
-- process. The difference, no sensitivity list and
-- an explict wait on clk statement at the end.
-- This process wants to be removed and replaced by
-- the above commented out process for synthesis
process (clk_txd, reset) -- , reset, enable) -- enable a reset?
begin
-- if enable = '0' then
if reset = '1' then -- puts q counter in known state for simulation
q <= "00000000";
elsif rising_edge(clk_txd) then
if q /= 255 then -- stop after sending once
q <= q + 1;
end if;
end if;
end process;
-- enable <= '1' when q <= 255 else '0'; -- this appears incorrect
enable <= '1' when q(3 downto 0) = "0010" else
'0';
clear <= '1' when q(3 downto 0) = "0001" else
'0';
-- USING ONE COUNTER requires some clocks output MARKS
-- (idle bits) each 16 clocks. It requires the load (enable)
-- occur once every 16 clocks.
-- q(3 downto 0) is selected for enable to prevent outputting spaces
-- TxD during reset (q is reset to all '0's). This would cause a receive
-- framing error.
process (q(7 downto 4))
begin
case q(7 downto 4) is
when "0000" => data <= x"40";
when "0001" => data <= x"41";
when "0010" => data <= x"42";
when "0011" => data <= x"43";
when "0100" => data <= x"44";
when "0101" => data <= x"45";
when "0110" => data <= x"46";
when "0111" => data <= x"47";
when "1000" => data <= x"48";
when "1001" => data <= x"49";
when "1010" => data <= x"50";
when "1011" => data <= x"51";
when "1100" => data <= x"52";
when "1101" => data <= x"53";
when "1110" => data <= x"54";
when "1111" => data <= x"55";
when others => data <= x"56";
end case;
end process;
process (clk_txd) -- , enable, data) -- synchronous enable and clear
begin
-- if enable = '1' then -- this appears incorrect
-- qtxd <= data;
if reset = '1' then
qtxd <= (others => '1'); -- outputs mark after reset
elsif rising_edge(clk_txd) then
if clear = '1' then -- synchronous clear for start bit
qtxd(0) <= '0';
elsif enable = '1' then -- synchronous load
qtxd <= data;
else
qtxd <= '1' & qtxd(7 downto 1); -- shift right
end if;
end if;
end process;
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture behavioral;
The comment table:
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
tells you where to find bits of the data(q(7 downto 0)) selected character. In the following waveform q is shown as hex to match:
You'll find with the fixes the first character transmitted is 0x40, the second 0x41,...

Trying to make a 4-bit multiplier in VHDL with 3x4 keypad input and 2x16 LCD to be implemented on a Spartan 3E board

everyone. I'm trying to make a 4-bit multiplier in VHDL. It is to be implemented on a Spartan 3E board using the built-in 2x16 LCD and a 3x4 keypad through a C922 IC.
Using it goes like this: user inputs a number through the keypad, presses a button for confirmation, enters a second number, presses the confirmation button again, and the product shows up on the LCD.
So far, the codes for the keypad+c922 and the LCD are okay. The code for the multiplier is almost okay. The problem is that the confirmation button only works when another number (which is not ultimately used) is pressed.
Here is my code. Following at are screenshots of the Xilinx simulation
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity multi_4bit is
Port ( CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
Input : in STD_LOGIC_VECTOR (3 downto 0);
DAVBL : in STD_LOGIC;
Confirm : in STD_LOGIC;
Output : out STD_LOGIC_VECTOR (7 downto 0));
end multi_4bit;
architecture Behavioral of multi_4bit is
type state is (R,S0,S1,S2,S3,S4);
signal pstate, nstate: state;
signal A_sig, B_sig: STD_LOGIC_VECTOR(3 downto 0);
begin
state_transition: process(CLK,RESET)
begin
if RESET = '1' then
pstate <= R;
elsif rising_edge(CLK) then
pstate <= nstate;
end if;
end process;
nstate_output: process(pstate,DAVBL,Input)
variable temp_var: STD_LOGIC_VECTOR(3 downto 0);
variable tempMult_var,tempProd_var: STD_LOGIC_VECTOR(7 downto 0);
begin
case pstate is
when R =>
nstate <= S0;
tempMult_var := (others => '0');
tempProd_var := (others => '0');
A_sig <= (others => '0');
B_sig <= (others => '0');
Output <= (others => '0');
when S0 =>
nstate <= S0;
if (DAVBL = '1') then
A_sig <= Input;
nstate <= S1;
end if;
when S1 =>
nstate <= S1;
if (Confirm = '1') then
nstate <= S2;
end if;
when S2 =>
nstate <= S2;
if (DAVBL = '1') then
B_sig <= Input;
nstate <= S3;
end if;
when S3 =>
nstate <= S3;
if (Confirm = '1') then
nstate <= S4;
end if;
when S4 =>
nstate <= S0;
for x in 0 to 3 loop
temp_var := (A_sig AND (B_sig(x)&B_sig(x)&B_sig(x)&B_sig(x) ) );
tempMult_var := "0000" & temp_var;
if (x=0) then tempMult_var := tempMult_var;
elsif (x=1) then tempMult_var := tempMult_var(6 downto 0)&"0";
elsif (x=2) then tempMult_var := tempMult_var(5 downto 0)&"00";
elsif (x=3) then tempMult_var := tempMult_var(4 downto 0)&"000";
end if;
tempProd_var := tempProd_var + tempMult_var;
end loop;
Output <= tempProd_var;
tempProd_var := (others => '0');
end case;
end process;
end Behavioral;
The simulation when no number is pressed with the confirmation button:
The simulation when a number is pressed with the confirmation button:
I've been going through my code for an hour now but still can't see what's wrong.
Thanks in advance to anyone who can help.
As mentioned by fru1tbat, Brian, and David, you have a problem with the sensitivity list in the combinatorial portion of your state machine. Specifically, you are missing the Confirm input. Since the Confirm input is not in the sensitivity list, the state machine will not "wake up" to evaluate new outputs/state transitions when confirm changes state. You need to wait for another condition (a different button press) in order to evaluate properly and update the output.
There are multiple ways that this can be resolved.
You can make sure you have a complete sensitivity list for your state machine logic
With VHDL-2008, you can use process(all) to automatically list all necessary inputs in the sensitivity list (your compiler support may vary).
You can choose to use a "single process state machine" style, which avoids this issue. However, different styles of state machines have their strengths and pitfalls that need to be considered.

Unintentional latches in finite state machine (VHDL) + feedback

This project is about adding user's custom peripheral core to MicroBlaze project on FPGA board "spartan 6 lx9". Using ISE Design Suite 14.6 and EDK.
My problem is being not enough experienced in writing VHDL code. I'm still getting 1-bit unintentional latches on signals: "data_bits" and "latest_value" from <0> til <15>, even though I have used recommended coding style for signal's assignment. I have set default values, but no success... Assignment of signal in each branch of case statement is not an option, since I want to retain value especially for "data_bits" since this vector is being build from several clock cycles. I'm trying to solve this problem for several days.
My questions are:
How I can fixed latches problem in this finite-state machine design? --Answered
I would like to get feedback on my state-machine design, styling etc. --Answered, but there is new code
Any design advice for staying on one state for several clocks cycles, using counters or there is a better technique? --Still expecting some advice
Initial Source Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity adc_16bit is
port(
clk : in std_logic;
rst : in std_logic;
data_reg_out : out std_logic_vector(31 downto 0);
control_reg : in std_logic_vector(31 downto 0);
SDO : in std_logic;
SCK : out std_logic;
CONV : out std_logic
);
end adc_16bit;
architecture Behavioral of adc_16bit is
type adc_states is (idle, conversation, clocking_low, clocking_high, receiving_bit, update_data);
signal State, NextState : adc_states;
signal data_bits : std_logic_vector(15 downto 0) := (others => '0');
signal latest_value : std_logic_vector(15 downto 0) := (others => '0');
signal conv_cnt : integer range 0 to 501 := 0;
signal clk_cnt : integer range 0 to 14 := 0;
signal bit_cnt : integer range 0 to 17 := 0;
begin
----------------------------------------------------------------------------------------
-- State Machine Register
----------------------------------------------------------------------------------------
StateReg:
process(clk, rst)
begin
if(clk'event and clk = '1') then
if(rst = '0') then
State <= idle;
else
State <= NextState;
end if;
end if;
end process StateReg;
----------------------------------------------------------------------------------------
-- Signals Register
----------------------------------------------------------------------------------------
TimerReg:
process(clk, rst)
begin
if(clk'event and clk = '1') then
--!default
conv_cnt <= conv_cnt;
clk_cnt <= clk_cnt;
bit_cnt <= bit_cnt;
--latest_value <= latest_value;
--data_bits <= data_bits;
case State is
when idle =>
conv_cnt <= 0;
clk_cnt <= 0;
bit_cnt <= 0;
when conversation =>
if(conv_cnt = 501) then
conv_cnt <= 0;
else
conv_cnt <= conv_cnt + 1;
end if;
when clocking_low =>
if(clk_cnt = 14) then
clk_cnt <= 0;
else
clk_cnt <= clk_cnt + 1;
end if;
when clocking_high =>
if(clk_cnt = 14) then
clk_cnt <= 0;
else
clk_cnt <= clk_cnt + 1;
end if;
when receiving_bit =>
if(bit_cnt = 16) then
bit_cnt <= 0;
else
bit_cnt <= bit_cnt + 1;
end if;
when update_data =>
end case;
end if;
end process TimerReg;
----------------------------------------------------------------------------------------
-- FSM Logic
----------------------------------------------------------------------------------------
FSM_Proc:
process(State, control_reg, conv_cnt, clk_cnt, bit_cnt )
begin
case State is
when idle =>
if(control_reg(0) = '1') then
NextState <= conversation;
else
NextState <= idle;
end if;
when conversation =>
if(conv_cnt = 500) then
NextState <= clocking_low;
else
NextState <= conversation;
end if;
when clocking_low =>
if(clk_cnt = 13) then
NextState <= clocking_high;
else
NextState <= clocking_low;
end if;
when clocking_high =>
if(clk_cnt = 13) then
NextState <= receiving_bit;
else
NextState <= clocking_high;
end if;
when receiving_bit =>
if(bit_cnt = 15) then
NextState <= update_data;
else
NextState <= clocking_low;
end if;
when update_data =>
if(control_reg(0) = '1') then
NextState <= conversation;
else
NextState <= idle;
end if;
end case;
end process FSM_Proc;
----------------------------------------------------------------------------------------
-- FSM Output
----------------------------------------------------------------------------------------
FSM_Output:
process(NextState, latest_value, data_bits, bit_cnt, SDO )
begin
--!default
CONV <= '0';
SCK <= '0';
data_reg_out(31 downto 16) <= (others => '0');
data_reg_out(15 downto 0) <= latest_value;
--data_bits <= data_bits;
--latest_value <= latest_value;
case NextState is
when idle =>
latest_value <= (others => '0');
data_bits <= (others => '0');
when conversation =>
CONV <= '1';
when clocking_low =>
SCK <= '0';
when clocking_high =>
SCK <= '1';
when receiving_bit =>
SCK <= '1';
--data_bits <= data_bits;
data_bits(bit_cnt) <= SDO;
when update_data =>
latest_value <= data_bits;
when others =>
--latest_value <= latest_value;
--data_bits <= data_bits;
end case;
end process FSM_Output;
end Behavioral;
EDIT
Thank you for all your responses! I decided to rewrite my FSM on single process and to add more information regarding my problem in order to make it more understandable for others who has similar problems!
Block Diagram of system:
http://i.stack.imgur.com/odCwR.png
Note: that right now I just want to simulate and verify stand alone adc_core itself without MicroBlaze and AXI interconnection block.
FSM Diagram:
http://i.stack.imgur.com/5qFdN.png
Single process source code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity adc_chip_driver is
port(
clk : in std_logic;
rst : in std_logic;
data_reg_out : out std_logic_vector(31 downto 0);
control_reg : in std_logic_vector(31 downto 0);
SDO : in std_logic;
SCK : out std_logic;
CONV : out std_logic
);
end adc_chip_driver;
architecture Behavioral of adc_chip_driver is
type states is (idle, conversation, clocking_low, clocking_high, receiving_bit, update_data);
signal state : states;
signal data_bits : std_logic_vector(0 to 15) := (others => '0');
signal latest_value : std_logic_vector(15 downto 0) := (others => '0');
signal conv_cnt : integer range 0 to 500 := 0;
signal clk_cnt : integer range 0 to 13 := 0;
signal bit_cnt : integer range 0 to 15 := 0;
begin
process(clk, rst, control_reg)
begin
if(rst = '0') then
state <= idle;
data_bits <= (others => '0');
latest_value <= (others => '0');
data_reg_out <= (others => '0');
elsif(clk'event and clk = '1') then
--!Default Values
data_reg_out(31 downto 16) <= (others => '0'); --unused bits of register
data_reg_out(15 downto 0) <= latest_value; --data_reg_out is always tided to latast_value;
latest_value <= latest_value; --latest_value is being updated only once
data_bits <= data_bits; --has to retain value
conv_cnt <= conv_cnt;
clk_cnt <= clk_cnt;
bit_cnt <= bit_cnt;
case state is
when idle =>
--signals
conv_cnt <= 0;
clk_cnt <= 0;
bit_cnt <= 0;
--outputs
SCK <= '0';
CONV <= '0';
--logic
if(control_reg(0) = '1') then
state <= conversation;
else
state <= idle;
end if;
when conversation =>
--output
SCK <= '0';
CONV <= '1';
--logic
if(conv_cnt = 500) then
state <= clocking_low;
conv_cnt <= 0;
else
state <= conversation;
conv_cnt <= conv_cnt + 1;
end if;
when clocking_low =>
--ouput
SCK <= '0';
CONV <= '0';
--logic
if(clk_cnt = 13) then
clk_cnt <= 0;
state <= clocking_high;
else
clk_cnt <= clk_cnt + 1;
state <= clocking_low;
end if;
when clocking_high =>
--ouput
SCK <= '1';
CONV <= '0';
--logic
if(clk_cnt = 13) then
clk_cnt <= 0;
state <= receiving_bit;
else
clk_cnt <= clk_cnt + 1;
state <= clocking_high;
end if;
when receiving_bit =>
--signal
data_bits(bit_cnt) <= SDO;
--ouput
SCK <= '1';
CONV <= '0';
--logic
if(bit_cnt = 15) then
bit_cnt <= 0;
state <= update_data;
else
bit_cnt <= bit_cnt + 1;
state <= clocking_low;
end if;
when update_data =>
--signal
latest_value(15 downto 0) <= data_bits(0 to 15);
--ouput
SCK <= '0';
CONV <= '0';
--logic
if(control_reg(0) = '1') then
state <= conversation;
else
state <= idle;
end if;
end case;
end if;
end process;
end Behavioral;
Maybe I could receive some new feedback on single process design?
Also I still do you have unanswered question regarding usage of counters in specific FSM states. I have noticed that usually during second cycle on "clocking_low" and "clocking_high" counter actually starts at 1 instead of 0, I know that in this situation it's not a problem, but I can easily imagine where it could be important. I was thinking about after reset set counters to '-1', but maybe there is better solution?
Your code has a number of problems. To illustrate some of them, I tried to sketch your finite state machine in Figs. 1 and 2 below, based on the VHDL code that you provided.
First and most importantly, the design should begin with a top-level block diagram, showing the circuit ports (as in Fig. 1), followed by a detailed state transition diagram (as in Fig. 2 – incomplete here). Recall, for example, that the circuit outputs (data_reg_out, SCK, and CONV – Fig. 1) are the signals that the FSM is supposed to produce, so it is indispensable that these values be specified in all states (shown inside the state circles in Fig. 2). Once the diagram of Fig. 2 is fixed and completed, writing a corresponding VHDL code should be relatively straightforward (except for the timer - see comments below).
Other problems can be seen directly in the code. Some comments on the four processes follow.
The first process (StateReg), which stores the FSM state, is fine.
The second process (TimerReg) is also registered (under clk’event), which is necessary to build the timer. However, dealing with timers is one of the trickiest parts of any timed FSM, because you MUST devise a correct strategy for stopping/running the timer and also for zeroing it. For this, I suggest that you check reference 1 below, which deals with all possible kinds of FSM implementations from a hardware perspective, including an extensive study of timed FSMs.
The third process (FSM_Proc) defines the next state. It is not registered, which is as it should be. However, to check it, it is necessary to complete first the state transition diagram of Fig. 2.
The last process (FSM_Output) defines the machine outputs. It is not registered, which is as it should be in general. However, the list of outputs is not the same in all states, in spite of the default values. Note, for example, the existence of latest_value and data_bits in state idle, which do not appear in all states, thus causing the inference of latches. Additionally, this process is based on NextState instead of PresentState, which (besides being awkward) might reduce the circuit’s maximum speed.
I hope these comments motivate you to restart from the beginning.
1 V. A. Pedroni, Finite State Machines in Hardware: Theory and Design (with VHDL and SystemVerilog), MIT Press, Dec. 2013.
You get a latch if a signal is not assigned to on all possible paths, as it then becomes stateful.
To avoid the problem, make sure you always assign a value to the signal (one way is to assign a "default" value at the top of the process).
since I want to retain value especially for "data_bits" since this vector is being build from several clock cycles.
"Retaining a value" means state, not purely combinatorial logic. In which case, it should not be in your output process. It should be in your state-update process.
My solution to this has been to always use clocked processes for everything. There is no need to have a separate clocked process for the state register and a separate process for the state transitions. That's a style which was required years ago. In my opinion, you are better off putting everything into a single clocked process and then you cannot get latches.
If you must use two processes then get a VHDL 2008 compiler and use process(all) to ensure that all your signals are correctly in the sensitivity list, and then carefully ensure that every signal you assign to gets an assignment for every logical path through the process. The easiest way to achieve this is often to assign them all some 'default' values at the start of the process.
In a combinational process (like FSM_Output), you should never read a signal and write to the same signal. That is exactly what is going on here, for latest_value and data_bits.
Either create new signals latest_value_r and data_bits_r and copy the values in the clocked process, or stick to a single clocked process with no separate combinational process.
What hardware do you want for data_bits and latest_value? If you want to build a vector over several clock cycles, then you need a storage device. Your choices are: latch (level sensitive storage) and flip-flop (edge sensitive storage). If you don't want latches, then you must code flip-flops.
To code flip-flops use the "if clk='1' and clk'event then", just like you did in TimerReg process. You can alternatively use "if rising_edge(Clk) then" - I like this better for readablity, but the tools don't care either way.
I think where you went wrong is in your planning process. Code is just design capture. What is important is that you plan with a block diagram and know where your design requires flip-flops and where it requires combinational logic. Get this right and the rest is just applying coding templates. So make sure you understand this before you start coding.
It does not matter whether you code with only clocked processes or use a mix of clocked and combinational logic processes. I think the most important thing you do in your coding is make it readable. If you collect opinions, you will see they vary, #Martin and #Brian prefer a single clocked process. I prefer a 2 process statemachine - flip-flop and combinational (present state to next state and ouput decode). You used a 3 process statemachine - for me that is like drawing a bubble diagram to show state transitions and a separate one to show the output transitions. However at the end of the day, they all capture the same intent. As long it is clear to someone reading your code long after you have left, it should be ok.

Resources