现在我制作一个测量温度和湿度的电路,然后在LCD上显示。这是我的DHT22代码,我使用的是Elbert V2。在完成我的项目后,它没有正确。
我测试了我的程序……
您的代码中存在许多错误。你是如何完全调试的?因为好像你没有。
为什么在复位后等待60 ms?你浪费(宝贵的)模拟时间。 6毫秒就足够了。
查看模拟输出,您可以看到 state 不进步 一点都不 :它被卡住了 wait_res_sl 。问题是您没有将过程中读取的所有信号添加到灵敏度列表中。即
state
wait_res_sl
bit_in ='1' and next_bit_in = '0'
如果不会检测到变化 next_bit_in 不在敏感列表中。
next_bit_in
一个问题 - 一个常见的错误 - 是你的'测试台'只提供输入刺激......但它实际上并没有测试任何东西。
然后是柜台。为什么延迟计数器被调用 index ?它没有索引任何东西。
index
为什么你的时间延迟与他们的标签不符? 70us - > 80我们28us - > 30我们
小东西不叫RTL架构 behavioral
behavioral
我试图清理你的代码,现在似乎工作。
library ieee; use ieee.std_logic_1164.all; entity dht2 is generic ( clk_period_ns : positive := 83; -- 12mhz data_width: positive:= 40); port( clk,rst : in std_logic ; singer_bus: inout std_logic; dataout: out std_logic_vector(data_width-1 downto 0); tick_done: out std_logic ); end entity; architecture rtl of dht2 is constant delay_1_ms: positive := 1*10**6/clk_period_ns+1; constant delay_40_us: positive := 40*10**3/clk_period_ns+1; constant delay_80_us: positive := 80*10**3/clk_period_ns+1; constant delay_50_us: positive := 50*10**3/clk_period_ns+1; -- constant time_70_us: positive := 70*10**3/clk_period_ns+1; --bit > 70 us constant time_28_us: positive := 28*10**3/clk_period_ns+1; -- bit 0 > 28 us constant max_delay : positive := 5*10**6/clk_period_ns+1; -- 5 ms signal input_sync : std_logic_vector(0 to 2); type state_type is (reset,start_m,wait_res_sl,response_sl,delay_sl,start_sl,consider_logic,end_sl); signal state : state_type; signal delay_counter : natural range 0 to max_delay; signal data_out : std_logic_vector (data_width-1 downto 0); signal bus_rising_edge, bus_falling_edge : boolean; signal number_bit : natural range 0 to data_width; signal oe: std_logic; -- help to set input and output port. begin input_syncronizer : process(clk) begin if rising_edge(clk) then input_sync <= to_x01(singer_bus)&input_sync(0 to 1); end if; end process; bus_rising_edge <= input_sync(1 to 2) = "10"; bus_falling_edge <= input_sync(1 to 2) = "01"; --register regis_state:process (clk) begin if rising_edge(clk) then case(state) is when reset => -- initial if delay_counter = 0 then number_bit <= data_width; oe <= '1'; delay_counter <= delay_1_ms; state <= start_m; else delay_counter <= delay_counter - 1; end if; when start_m => -- master send '1' in 1ms if delay_counter = 0 then oe <= '0'; delay_counter <= delay_40_us; state <= wait_res_sl; else delay_counter <= delay_counter -1; end if ; when wait_res_sl => -- wait for slave response in 40us -- if bus_falling_edge then -- state <= response_sl; end if; when response_sl => -- slave response in 80us if bus_rising_edge then state <= delay_sl; end if; when delay_sl => -- wait for slave delay in 80us if bus_falling_edge then state <= start_sl; end if; when start_sl => -- start to prepare in 50us if bus_rising_edge then delay_counter <= 0; state <= consider_logic; elsif number_bit = 0 then delay_counter <= delay_50_us; state <= end_sl; end if; when consider_logic => -- determine 1 bit-data of slave if bus_falling_edge then -- the end of logic state number_bit <= number_bit - 1; if (delay_counter < time_28_us) then -- time ~ 28 us - logic = '0' data_out <= data_out(data_width-2 downto 0) & '0'; elsif (delay_counter < time_70_us) then -- time ~70 us - logic ='1' data_out <= data_out(data_width-2 downto 0) & '1'; end if; delay_counter <= delay_50_us; state <= start_sl; end if; delay_counter <= delay_counter + 1; when end_sl => -- tick_done = '1' then dataout has full 40 bit. if delay_counter = 0 then delay_counter <= max_delay; state <= reset; else tick_done <= '1'; dataout <= data_out; delay_counter <= delay_counter - 1; end if; end case; if rst = '1' then number_bit <= 0; data_out <= (others => '0'); delay_counter <= max_delay; state <= reset; end if; end if; end process regis_state; --tristate iobuffer singer_bus <= '0' when oe ='1' else 'Z'; end architecture;
和测试台:我添加了一张支票,但是你应该做更多的检查:每次做某事时,都应该有效果。你应该测试这种效果是否真的发生了。
entity dht2_tb is end dht2_tb; library ieee; architecture behavior of dht2_tb is use ieee.std_logic_1164.all; --inputs signal clk : std_logic := '0'; signal rst : std_logic := '0'; --bidirs signal singer_bus : std_logic := 'H'; --outputs signal tick_done : std_logic; -- clock period definitions constant clk_period : time := 83.33 ns; -- 12mhz use ieee.math_real.all; -- This function generates a 'slv_length'-bit std_logic_vector with -- random values. function random_slv(slv_length : positive) return std_logic_vector is variable output : std_logic_vector(slv_length-1 downto 0); variable seed1, seed2 : positive := 65; -- required for the uniform function variable rand : real; -- Assume mantissa of 23, according to IEEE-754: -- as UNIFORM returns a 32-bit floating point value between 0 and 1 -- only 23 bits will be random: the rest has no value to us. constant rand_bits : positive := 23; -- for simplicity, calculate remaining number of bits here constant end_bits : natural := slv_length rem rand_bits; use ieee.numeric_std.all; begin -- fill sets of 23-bit of the output with the random values. for i in 0 to slv_length/rand_bits-1 loop uniform(seed1, seed2, rand); -- create random float -- convert float to int and fill output output((i+1)*rand_bits-1 downto i*rand_bits) := std_logic_vector(to_unsigned(integer(rand*(2.0**rand_bits)), rand_bits)); end loop; -- fill final bits (< 23, so above loop will not work. uniform(seed1, seed2, rand); if end_bits /= 0 then output(slv_length-1 downto slv_length-end_bits) := std_logic_vector(to_unsigned(integer(rand*(2.0**end_bits)), end_bits)); end if; return output; end function; -- input + output definitions constant test_data_length : positive := 32; constant test_data : std_logic_vector(test_data_length-1 downto 0) := random_slv(test_data_length); signal data_out : std_logic_vector(test_data_length-1 downto 0); begin -- instantiate the unit under test (uut) uut: entity work.dht2 -- use entity instantiation: no component declaration needed generic map ( clk_period_ns => clk_period / 1 ns, data_width => test_data_length) port map ( clk => clk, rst => rst, singer_bus => singer_bus, dataout => data_out, tick_done => tick_done ); -- clock stimuli clk_process: process begin clk <= '0', '1' after clk_period/2; wait for clk_period; end process; -- reset stimuli rst_proc : process begin rst <= '1', '0' after 100 us; wait; end process; -- bidir bus pull-up -- as you drive the bus from the uut and this test bench, it is a bidir -- you need to simulate a pull-up ('H' = weak '1'). slv will resolve this. singer_bus <= 'H'; -- stimulus process bus_proc: process -- we use procedures for stimuli. Increases maintainability of test bench -- procedure bus_init initializes the slave device. (copied this from your code) procedure bus_init is begin -- singer_bus <= 'Z'; -- initial wait for 6 ms; -- singer_bus <= '0'; -- master send -- wait for 1 ms; singer_bus <= 'Z'; -- wait response for slave wait for 40 us; singer_bus <= '0'; -- slave pull low wait for 80 us; singer_bus <= 'Z'; -- slave pull up wait for 80 us; end procedure; function to_string(input : std_logic_vector) return string is variable output : string(1 to input'length); variable j : positive := 1; begin for i in input'range loop output(j) := std_logic'image(input(i))(2); j := j + 1; end loop; return output; end function; -- procedure send_data procedure send_data(data : std_logic_vector) is begin -- we can now send a vector of data,length detected automatically for i in data'range loop singer_bus <= '0'; -- slave start data transmission wait for 50 us; singer_bus <= 'Z'; -- slave send bit; -- I found the only difference between sending bit '0' -- and '1' is the length of the delay after a '0' was send. case data(i) is when '0' => wait for 24 us; when '1' => wait for 68 us; when others => report "metavalues not supported for bus_proc send_data" severity failure; end case; singer_bus <= '0'; end loop; -- next is VHDL-2008 (else use ieee.std_logic_textio.all;) report "transmitted: "&to_string(data); end procedure; begin wait until rst = '0'; bus_init; -- call procedure send_data(test_data); -- call procedure wait for 100 us; -- final delay singer_bus <= 'Z'; -- release bus report "received: "&to_string(data_out); -- test correctness of output assert data_out = test_data report "data output does not match send data" severity error; report "end of simulation" severity failure; end process; end architecture;