Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

VHDL Time Delay Problem?

Status
Not open for further replies.

Batur

Newbie level 4
Newbie level 4
Joined
Oct 30, 2015
Messages
6
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
82
Hi there, i am a new engineer who is trying to learn FPGA programming. As a project i am trying to implement a digital thermometer using a spartan3e FPGA board and DS1822 chip which uses 1-wire protocol.

For starters i am just trying to implement the preset and present pulses between the devices but when i try to test my code simulation gets stuck at the first delay.

Can anyone point me what i am doing wrong. Thanks in advance for your help!

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity main is
port (
		clk : in STD_LOGIC;
		onoff : in STD_LOGIC;
		DQ : inout STD_LOGIC;
		led_test : out STD_LOGIC);

end main;



architecture Behavioral of main is



signal DQ_in: STD_LOGIC;
signal dev_present: STD_LOGIC; -- 1 if device answers.
signal new_clk: STD_LOGIC:='0'; -- 2us clock
signal onoff_in: STD_LOGIC:='0'; -- 2us clock

begin

onoff_in <=onoff;

clk_proc: process (clk)

variable clk_cnt: integer:=0; 

begin

if rising_edge(clk) then --Mclk 20ns
clk_cnt := clk_cnt+1;
	
	if (clk_cnt = 100) then
	clk_cnt := 0;
	new_clk <= not new_clk;--2 us clk
	end if;
	
end if;
end process;



-- 1wire bus pulled low for min 480us by master => "reset"
p1: process(new_clk,onoff_in)  

variable loop_cnt: integer:=0; 

begin
if (onoff_in = '1') then

--wait 1ms
while (loop_cnt < 501) loop
	if rising_edge(new_clk) then
	loop_cnt:= loop_cnt + 1;
	end if;
end loop;
loop_cnt:=0; --reset counter


DQ <= '0'; --pull bus low


--wait 500us
while (loop_cnt < 251) loop
	if rising_edge(new_clk) then
	loop_cnt:= loop_cnt + 1;
	end if;
end loop;
loop_cnt:=0; --reset counter


DQ <='Z';-- pullup resistor restores DQ bus to high



-- slave detects bus rising to pullup waits 15 to 60us then pulls bus low for 60 to 240us => "present"
  
--wait 90us for slave 

while (loop_cnt < 46) loop
	if rising_edge(new_clk) then
	loop_cnt:= loop_cnt + 1;
	end if;
end loop;
loop_cnt:=0; --reset counter

end if;
end process;

DQ_in <=DQ;                 --sample DQ
dev_present<= not DQ_in;



led_test<=dev_present;


end Behavioral;
 

You're p1 process looks like you are trying to write software (and the fact that you called the entity main).

All of the statements are run in parallel. I'm not even sure the while loops will work correctly as a delay, but as I never write code like that I could be wrong and they do work as you expect. I would instead write a single counter (not using a variable) and have a case or if statement that determines when to assert/remove the output signals or write and FSM with a counter that is used to do the same (note: a counter is a simple FSM).

Also using variables is IMO a bad practice to get into when writing hardware, especially if you are new at using VHDL. If you want a FF use a signal, using variables it's dependent on how the variable is used whether a FF gets inferred or not. So don't use variables, anything you can write using a variable can be written using signals.

also you don't write tristate bi-directional logic for DQ like you have as sequential statements.
Code:
DQ <= out_val when (dq_enable = '1') else 'Z';
 
  • Like
Reactions: Batur

    Batur

    Points: 2
    Helpful Answer Positive Rating
process p1 is written similar to a sequential software description of a solution. The way a process works is different.

you want to have a process that looks more like this:
Code:
p1 : process (new_clk) is
begin
  if rising_edge(new_clk) then
    if onoff = '1' then -- this seems to be a clock enable
      cnt <= cnt + 1; -- default
      case (state) is
      when WAIT_1MS =>
        if cnt >= CNT_1MS then -- might be off by 1 if not careful
          cnt <= 0; -- reset count for next wait
          DQ <= '0'; -- this might need to be broken up to DQ_oe and DQ_val
        end if;
      -- add other states here
      end case;
    end if;
  end if;
end process;
 
  • Like
Reactions: Batur

    Batur

    Points: 2
    Helpful Answer Positive Rating
Code:
          DQ <= '0'; -- this might need to be broken up to DQ_oe and DQ_val

As the description in the OP is about DQ being pulled up...

Code:
DQ_pin <= DQ when (DQ = '0') else 'Z';
then the vGoodtimes code would work as long as the pin assignment is like above.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top