VHDL требуется временная задержка в последовательном списке операторов CASE - PullRequest
0 голосов
/ 06 августа 2020

У меня ядро ​​8051 работает как главный модуль верхнего уровня в моей FPGA. Затем у меня есть подпрограмма I2 C (здесь я делаю только 8051 ведущее устройство для ведомого светодиодного дисплея), также созданная здесь. 8051 отправляет параллельный адрес I2 C и данные в подпрограмму I2 C, а данные I2 C поступают в мой осциллограф Salela. Это работает, НО, у меня проблема, и мне нужна временная задержка, и я просто не понимаю, как это сделать. Это не для тестового стенда или модельного ряда, это реально. Когда процедура I2 C занята, она устанавливает бит «занято» в высокий уровень, и 8051 опрашивает его, а когда бит занятости становится низким, 8051 затем отправляет следующие 8 бит параллельных данных в процедуру I2 C. Проблема в том, что процедура I2 C слишком быстро переключает этот бит «занято», и 8051 не может вовремя передать свои данные в процедуру I2 C. Мне нужно, чтобы процедура I2 C сидела и немного ждала сразу после того, как бит занятости опустится. Вот где он мне нужен.

WHEN slv_ack2 =>                  
            IF(ena = '1') THEN                  
              busy <= '0';     -- I2C routine sets busy bit to low for 8051 to send data

              I need to wait here for 1 full second all the time when at this step

              
              addr_rw <= addr & rw;          
              data_tx <= data_wr;            
              IF(addr_rw = addr & rw) THEN   
                sda_int <= data_wr(bit_cnt); 
                state <= wr;                 
              ELSE                           
                state <= stop;              
              END IF;
              
WHEN wr =>                         -
            busy <= '1';                     
            IF(bit_cnt = 0) THEN             
              sda_int <= '1';                
              bit_cnt <= 7;                  
              state <= slv_ack2;             
            ELSE                             
              bit_cnt <= bit_cnt - 1;        
              sda_int <= data_tx(bit_cnt-1); 
              state <= wr;                   
            END IF;           
 

Да, я нашел красивый счетчик, и я ясно вижу, что он делает, но куда его вставить и как его использовать? Хорошо, я новичок в VHDL / FPGA, но сейчас около 4 недель, так что все еще обучение, синтаксис и размещение - мои самые большие возражения до сих пор. так не работает. Куда поставить, чтобы он заработал?


WHEN slv_ack2 =>                  
            IF(ena = '1') THEN               
              busy <= '0';
              
              

                  PROCESS (timer)
BEGIN
IF (clk12'EVENT AND clk12 = '1') THEN
    counter <= counter + '1';
    if( counter = 1 ) then
        SIGNAL_COUNTED <= '1';
        counter <= "0";
    else
        SIGNAL_COUNTER <= '0';
    end if;
END IF;
END PROCESS;


              
              addr_rw <= addr & rw;          
              data_tx <= data_wr;            
              IF(addr_rw = addr & rw) THEN   
                sda_int <= data_wr(bit_cnt); 
                state <= wr;                 
              ELSE                           
                state <= stop;              
              END IF;
              
WHEN wr =>                         -
            busy <= '1';                     
            IF(bit_cnt = 0) THEN             
              sda_int <= '1';                
              bit_cnt <= 7;                  
              state <= slv_ack2;             
            ELSE                             
              bit_cnt <= bit_cnt - 1;        
              sda_int <= data_tx(bit_cnt-1); 
              state <= wr;                   
            END IF;           

1 Ответ

0 голосов
/ 07 августа 2020

Когда вы пишете VHDL, вам нужно помнить, что вы описываете оборудование, поэтому полезно подумать о том, какой будет лежащая в основе схема. В этом случае вы пытаетесь реализовать функцию типа сна, поэтому вы в основном хотите, чтобы ваш FSM ничего не делал, пока счетчик не истечет время ожидания.

Для этого вам нужно добавить другое состояние, которое ждет счетчик достигнет 0 (при условии, что вы используете обратный счетчик для реализации счетчика). Например:

WHEN slv_ack2 =>                  
    IF(ena = '1') THEN                  
         busy  <= '0';
         state <= sleep;
    END IF;

WHEN sleep =>
    IF (timer = 0) THEN
        state        <= setup_write;
        enable_timer <= '0';
    ELSE
        enable_timer <= '1';
    END IF;

WHEN setup_write =>
    addr_rw <= addr & rw;          
    data_tx <= data_wr;            
    IF(addr_rw = addr & rw) THEN   
        sda_int <= data_wr(bit_cnt); 
        state <= wr;                 
    ELSE                           
        state <= stop;              
    END IF;

Для кода счетчика вы не можете поместить блок процесса внутри другого блока процесса. Поэтому вам нужно переместить его за пределы оператора case. Вы также хотите, чтобы он вел активный счет только тогда, когда вы фактически находитесь в состоянии сна, поэтому вам нужно будет добавить к нему сигнал включения.

...