Перейти к содержанию
    

Как ModelSim определяет, произощёл ли переход между состояниями в FSM?

Всем добра!

Есть код

module fsm_dut(

    input logic reset,
    input logic clk,
    input logic a,
    input logic we,
    input logic [2:0] mode,
    input logic w,

    output logic fsm_state_stop,
    output logic fsm_state_op1,
    output logic fsm_state_op2,
    output logic fsm_state_op3,
    output logic fsm_state_finish
    
);

    enum logic [2:0] {stop, op1, op2, op3, finish} fsm;

    always @(posedge reset or posedge clk)
        if (reset)
            fsm <= stop;
        else
            case (fsm)
            stop :
                if (a)
                    fsm <= op1;
                else
                    fsm <= finish;
            op1 :	
                if (~we)
                    fsm <= op1;
                else
                    if (mode == 3'd4)
                        fsm <= op2;
                    else
                        fsm <= finish;
            op2 :	
                fsm <= op3;
            op3 :	
                fsm <= finish;
            finish :
                if (w | ~a)
                    fsm <= finish;
                else
                    fsm <= op1;
            endcase
    
    assign  fsm_state_stop   = fsm == stop;
    assign  fsm_state_op1    = fsm == op1;
    assign  fsm_state_op2    = fsm == op2;
    assign  fsm_state_op3    = fsm == op3;
    assign  fsm_state_finish = fsm == finish;    

endmodule :  fsm_dut   

И есть testbench

`timescale 1ns / 10ps

module fsm_tb;

    logic reset;
    logic clk;
    logic a;
    logic we;
    logic [2:0] mode;
    logic w;
    
    logic fsm_state_stop;
    logic fsm_state_op1;
    logic fsm_state_op2;
    logic fsm_state_op3;
    logic fsm_state_finish;

    fsm_dut fsm_dut(.*);
    
    initial begin
        clk = '0;
        forever #10ns clk = ~clk;
    end
    
    initial begin
        reset = '0;
        #5ns reset = '1;
        #10ns reset = '0;
    end
    
    initial begin
        a = '0;
        we = '0;
        mode = '0;
        w = '0;
        #25ns force fsm_dut.fsm = fsm_dut.op2;
        release fsm_dut.fsm;
        #1ns force fsm_dut.clk = '1;
        #1ns force fsm_dut.clk = '0;
        #20ns $stop;            
    end

endmodule :  fsm_tb 

главная цель которого установить машину fsm модуля fsm_dut в состояние op2 и дёрнуть clk, по которому, судя по описанию машины в модуле fsm_dut эта машина перейдёт в состояние op3.

Если вывожу временную диаграмму, то машина в заданный момент времени переходит, как положено (показано в максимальном приближении):

1260136370_02.thumb.gif.f17c8c320bd672b0c2c78590b491a3fd.gif

Но если глянуть покрытие кода, то переход остаётся недетектированным. Почему?

1358014546_03.thumb.gif.00d686d680b5dea55679d20aa581cf5b.gif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После долгих разборок установлено, что ModelSim считает покрытыми только переходы, совершённые "естественным" путём, т.е. такие, которые произошли по фронту исходной тактовой частоты, а состояния, переходы между которыми "засчитываются" также должны быть "насильно не установлены". Итого: играть (устанавливать (force/release)) можно только сигналами разрешения перехода между состояниями и сигналом сброса машины, состояния же самой машины и её тактирование трогать нельзя.
 

`timescale 1ns / 1ns
`define T1ns    1                   // with respect to timebase (1ns)
`define T1us    1000*`T1ns

module fsm_tb;

    logic reset;
    logic clk;
    logic a;
    logic we;
    logic [2:0] mode;
    logic w;
    
    logic fsm_state_stop;
    logic fsm_state_op1;
    logic fsm_state_op2;
    logic fsm_state_op3;
    logic fsm_state_finish;
    
    integer file_stop_time;
    integer curr_time, us, ns;        

    fsm_dut fsm_dut(.*);
    
    initial begin
        clk = '0;
        forever #10ns clk = ~clk;
    end
    
    initial begin
        reset = '0;
        #5ns reset = '1;
        #1ns reset = '0;
    end
    
    initial
        $monitor("@%2tns fsm.state = %s", $stime, fsm_dut.fsm.name());
    
    initial begin
    
        a = '1;
        we = '0;
        mode = '0;
        w = '0;
        #25ns 
        
        @(posedge fsm_dut.clk) // stop -> op1

        force fsm_dut.we = '1;
        force fsm_dut.mode = 3'd4;
        @(posedge fsm_dut.clk) // op1 -> op2
        
        @(posedge fsm_dut.clk) // op2 -> op3
        
        @(posedge fsm_dut.clk) // op3 -> finish
        
        force fsm_dut.w = '0;
        force fsm_dut.a = '1; 
        @(posedge fsm_dut.clk) // finish -> op1
        
        force fsm_dut.mode = 3'd0;
        @(posedge fsm_dut.clk) // op1 -> finish
        
        #10ns
        force fsm_dut.reset = '1; // finish -> stop
        #1ns release fsm_dut.reset;
        
        force fsm_dut.a = '0; 
        @(posedge fsm_dut.clk) // stop -> finish 
        
        force fsm_dut.a = '1;
        @(posedge fsm_dut.clk) // finish -> op1

        #10ns
        force fsm_dut.reset = '1; // op1 -> stop
        #1ns release fsm_dut.reset;        
        
        @(posedge fsm_dut.clk) // stop -> op1

        force fsm_dut.we = '1;
        force fsm_dut.mode = 3'd4;
        @(posedge fsm_dut.clk) // op1 -> op2       

        #10ns
        force fsm_dut.reset = '1; // op2 -> stop
        #1ns release fsm_dut.reset; 

        @(posedge fsm_dut.clk) // stop -> op1

        force fsm_dut.we = '1;
        force fsm_dut.mode = 3'd4;
        @(posedge fsm_dut.clk) // op1 -> op2           
        
        @(posedge fsm_dut.clk) // op2 -> op3
        
        #10ns
        force fsm_dut.reset = '1; // op3 -> stop
        #1ns release fsm_dut.reset; 
     
    end

endmodule :  fsm_tb  
# @ 0ns fsm.state = 
# @ 5ns fsm.state = stop
# @10ns fsm.state = op1
# @50ns fsm.state = op2
# @70ns fsm.state = op3
# @90ns fsm.state = finish
# @110ns fsm.state = op1
# @130ns fsm.state = finish
# @140ns fsm.state = stop
# @150ns fsm.state = finish
# @170ns fsm.state = op1
# @180ns fsm.state = stop
# @190ns fsm.state = op1
# @210ns fsm.state = op2
# @220ns fsm.state = stop
# @230ns fsm.state = op1
# @250ns fsm.state = op2
# @270ns fsm.state = op3
# @280ns fsm.state = stop
# @290ns fsm.state = op1 

Clipboard04.thumb.gif.770c4b756d077ad5da51f3f53770fb04.gif

Clipboard05.gif.1f3dddd46c9e18e5ec92a605e86bce25.gif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, например, читать состояние полезно, если нужно сбросить машину. А так, да, обошелся тем, что заложено.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

33 minutes ago, MaratZuev said:

Ну, например, читать состояние полезно, если нужно сбросить машину. А так, да, обошелся тем, что заложено.

Извините, а где вас так "научили", что вы думаете, что форсить - это читать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 minutes ago, one_eight_seven said:

Извините, а где вас так "научили", что вы думаете, что форсить - это читать?

Извините, а где вас так "научили", что вы думаете, что форсить и форсировать - это одно и тоже?
Я говорил в общем, а вы пытаетесь придраться к словам.
Прочитайте все мои посты в этом треде, прежде чем высказываться не по-существу. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 minutes ago, AnatolySh said:

Извините, а где вас так "научили", что вы думаете, что форсить и форсировать - это одно и тоже?
Я говорил в общем, а вы пытаетесь придраться к словам.
Прочитайте все мои посты в этом треде, прежде чем высказываться не по-существу. 

1. Я цитировал не вас

2. К словам придираетесь вы.

3. Даже не подумаю читать все ваши посты, потому что мне хватило этого бреда, в котором прекрасно всё: и упоминание какого-то "разговора в общем", когда топикстартера спросили о конкретике, и то, что попытку вернуться к конкретике вы называете "придиркой к словам", и попытки указать мне что делать... вы кем себя возомнили? Боженькой пресвятым? Так нет, вы просто несмешной твинк какой-то, вам бы книжку по логике почитать, для средней школы.

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, и если вы, one_eight_sevenзахотите что-то сказать насчёт двух аккаунтов, то, прошу, воздержитесь. Их у меня, действительно, не один, но, полагаю, что этим я ничего не нарушаю.
И снова прошу: давайте по-существу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 hours ago, MaratZuev said:

Да, и если вы, one_eight_sevenзахотите что-то сказать насчёт двух аккаунтов, то, прошу, воздержитесь. Их у меня, действительно, не один, но, полагаю, что этим я ничего не нарушаю.
И снова прошу: давайте по-существу.

Напрасно вы так думаете . Правила форума запрещают регистрироваться на форуме несколько раз под разными никами , пункт 3.5 .

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, что указали: возможно, либо читал правила по диагонали, либо такого пункта не было, когда вступал.

Не нашёл, как удалить аккаунт, посему остаётся только принять на себя обязательство вторым не пользоваться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...