преобразовать verilog в FSM

У меня есть программа, написанная на Verilog, и я хочу автоматически преобразовать ее в FSM. Возможно ли это (просто для наглядности)?

Вот код:

module pci(reset,clk,frame,irdy,trdy,devsel,idsel,ad,cbe,par,stop,inta,led_out);
    input reset;
    input clk;
    input frame;
    input irdy;
    output trdy;
    output devsel;
    input idsel;
    inout [31:0] ad;
    input [3:0] cbe;
    inout par;
    output stop;
    output inta;
    output [3:0] led_out;

parameter DEVICE_ID = 16'h9500;
parameter VENDOR_ID = 16'h106d;     // Sequent!
parameter DEVICE_CLASS = 24'hFF0000;    // Misc
parameter DEVICE_REV = 8'h01;
parameter SUBSYSTEM_ID = 16'h0001;  // Card identifier
parameter SUBSYSTEM_VENDOR_ID = 16'hBEBE; // Card identifier
parameter DEVSEL_TIMING = 2'b00;    // Fast!

reg [2:0] state;
reg [31:0] data;

reg [1:0] enable;
parameter EN_NONE = 0;
parameter EN_RD = 1;
parameter EN_WR = 2;
parameter EN_TR = 3;

reg memen; // respond to baseaddr?
reg [7:0] baseaddr;
reg [5:0] address;

parameter ST_IDLE = 3'b000;
parameter ST_BUSY = 3'b010;
parameter ST_MEMREAD = 3'b100;
parameter ST_MEMWRITE = 3'b101;
parameter ST_CFGREAD = 3'b110;
parameter ST_CFGWRITE = 3'b111;

parameter MEMREAD = 4'b0110;
parameter MEMWRITE = 4'b0111;
parameter CFGREAD = 4'b1010;
parameter CFGWRITE = 4'b1011;

`define LED
`ifdef LED
reg [3:0] led;
`endif

`undef STATE_DEBUG_LED
`ifdef STATE_DEBUG_LED
assign led_out = ~state;
`else
`ifdef LED
assign led_out = ~led;  // board is wired for active low LEDs
`endif
`endif

assign ad = (enable == EN_RD) ? data : 32'bZ;
assign trdy = (enable == EN_NONE) ? 'bZ : (enable == EN_TR ? 1 : 0);
assign par = (enable == EN_RD) ? 0 : 'bZ;
reg devsel;

assign stop = 1'bZ;
assign inta = 1'bZ;

wire cfg_hit = ((cbe == CFGREAD || cbe == CFGWRITE) && idsel && ad[1:0] == 2'b00);
wire addr_hit = ((cbe == MEMREAD || cbe == MEMWRITE) && memen && ad[31:12] == {12'b0, baseaddr});
wire hit = cfg_hit | addr_hit;

always @(posedge clk)
begin
    if (~reset) begin
        state <= ST_IDLE;
        enable <= EN_NONE;
        baseaddr <= 0;
        devsel <= 'bZ;
        memen <= 0;
`ifdef LED
        led <= 0;
`endif
    end
    else    begin

    case (state)
        ST_IDLE: begin
            enable <= EN_NONE;
            devsel <= 'bZ;
            if (~frame) begin
                address <= ad[7:2];
                if (hit) begin
                    state <= {1'b1, cbe[3], cbe[0]};
                    devsel <= 0;
                    // pipeline the write enable
                    if (cbe[0])
                        enable <= EN_WR;
                end
                else begin
                    state <= ST_BUSY;
                    enable <= EN_NONE;
                end
            end
        end

        ST_BUSY: begin
            devsel <= 'bZ;
            enable <= EN_NONE;
            if (frame)
                state <= ST_IDLE;
        end

        ST_CFGREAD: begin
            enable <= EN_RD;
            if (~irdy || trdy) begin
                case (address)
                    0: data <= { DEVICE_ID, VENDOR_ID };
                    1: data <= { 5'b0, DEVSEL_TIMING, 9'b0,  14'b0, memen, 1'b0};
                    2: data <= { DEVICE_CLASS, DEVICE_REV };
                    4: data <= { 12'b0, baseaddr, 8'b0, 4'b0010 }; // baseaddr + request mem < 1Mbyte
                    11: data <= {SUBSYSTEM_ID, SUBSYSTEM_VENDOR_ID };
                    16: data <= { 24'b0, baseaddr };
                    default: data <= 'h00000000;
                endcase
                address <= address + 1;
            end
            if (frame && ~irdy && ~trdy) begin
                devsel <= 1;
                state <= ST_IDLE;
                enable <= EN_TR;
            end
        end

        ST_CFGWRITE: begin
            enable <= EN_WR;
            if (~irdy) begin
                case (address)
                    4: baseaddr <= ad[19:12];  // XXX examine cbe
                    1: memen <= ad[1];
                    default: ;
                endcase
                address <= address + 1;
                if (frame) begin
                    devsel <= 1;
                    state <= ST_IDLE;
                    enable <= EN_TR;
                end
            end
        end

        ST_MEMREAD: begin
            enable <= EN_RD;
            if (~irdy || trdy) begin
                case (address)
`ifdef LED
                    0: data <= { 28'b0, led };
`endif
                    default: data <= 'h00000000;
                endcase
                address <= address + 1;
            end
            if (frame && ~irdy && ~trdy) begin
                devsel <= 1;
                state <= ST_IDLE;
                enable <= EN_TR;
            end
        end

        ST_MEMWRITE: begin
            enable <= EN_WR;
            if (~irdy) begin
                case (address)
`ifdef LED
                    0: led <= ad[3:0];
`endif
                    default: ;
                endcase
                address <= address + 1;
                if (frame) begin
                    devsel <= 1;
                    state <= ST_IDLE;
                    enable <= EN_TR;
                end
            end
        end

    endcase
    end
end
endmodule

Если нет автоматического способа, не могли бы вы объяснить, как это сделать?

Вот FSM, сделанный вручную, но проверить не могу, так что...

fsm

Вроде нормально?


person fizampou    schedule 16.02.2013    source источник
comment
Я не понимаю, что вы спрашиваете. У вас есть FSM, написанный на Verilog. Что вы имеете в виду под «преобразовать его в FSM»? Вы имеете в виду что-то конкретное для определенного симулятора или какой результат вы ожидаете?   -  person Tim    schedule 16.02.2013
comment
я имею в виду, как я могу визуализировать это как изображение, которое я только что добавил автоматически.   -  person fizampou    schedule 16.02.2013


Ответы (3)


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

С помощью инструментов cadence вы можете запустить свой код с «покрытием кода», после чего imc сможет загрузить данные о покрытии и запустить анализ FSM.

Я включил простой FSM ниже и показываю сгенерированную диаграмму состояний.

module simple_fsm(); 
  //Inputs to FSM
  logic clk;
  logic rst_n;

  logic [1:0] state    ;
  logic [1:0] nextstate;
  logic       turn_on  ;
  logic       turn_off ;

  localparam  S_OFF    = 2'b00;
  localparam  S_GO_ON  = 2'b01;
  localparam  S_ON     = 2'b10;
  localparam  S_GO_OFF = 2'b11;

  // State FlipFlop
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      state <= 2'b0;
    end
    else begin
      state <= nextstate;
    end
  end

  //Nextstate Logic
  always @* begin
    case (state)
      2'd0 : if (turn_on) begin
        nextstate = S_GO_ON;
      end
      2'd1 : nextstate = S_ON;
      2'd2 : if (turn_off) begin
        nextstate = S_GO_OFF ;
      end
      2'd3 : nextstate = S_OFF;
    endcase
  end    

//TB clk
initial begin
 #1ns;
 clk = 0;
 forever begin
  #20ns;
  clk = ~clk;
 end
end

//The Test
initial begin
  rst_n    = 1'b0;
  turn_on  = 1'b0;
  turn_off = 1'b0;
  @(posedge clk);
  @(posedge clk);
  rst_n = 1'b1 ;

  @(posedge clk);
  turn_on = 1'b1;
  @(posedge clk);
  turn_on = 1'b0;

  @(posedge clk);
  @(posedge clk);
  #100ms;

  $finish();
end
endmodule

Выполнить с помощью:

$ irun simple_fsm.sv -coverage all -covdut simple_fsm
$ imc &

Загрузите cov_work (папку, созданную вышеприведенным моделированием) в imc, выберите simple_fsm и выберите FSM Analysis.

simple_fsm визуализация

imc также помогает визуализировать покрытие тестами. Дуги и состояния, которые не были затронуты, показаны красным.

Мы видели, что есть некоторые инструменты, которые могут визуализировать FSM, другая часть вопроса; синтаксис целевого FSM подходит для этих инструментов.

@vermaete сообщил, что Modelsim SE не видит FSM. Из imc я получаю:

OPs FSM from Question

Который, кажется, не охватывает сложность кода и показан как имеющий только 2 достижимых состояния: IDLE и BUSY. Я бы рекомендовал, если OP идет по пути использования инструментов для визуализации, принять более простую (синтаксическую) структуру FSM, чтобы инструменты могли лучше анализировать ее.

person Morgan    schedule 19.02.2013
comment
Не могли бы вы поделиться графиком с FSM вопроса? Modelsim SE не обнаружил FSM. - person vermaete; 19.02.2013

Более качественные и дорогие симуляторы могут обнаруживать автоматы в коде и визуализировать их. Например. Версия Modelsim SE. Это может быть полезно для понимания кода и проверки покрытия. Но сделать свой собственный рисунок FSM с 6 состояниями не так уж и сложно.

person vermaete    schedule 16.02.2013
comment
Я добавил fsm, сделанный вручную, но не могу проверить, все ли в порядке. - person fizampou; 16.02.2013
comment
Какой симулятор вы используете? Есть ли у него «покрытие кода»? Если это так, вы можете создать тестовый стенд, который должен запускать все состояния, и проверить после моделирования, так ли это. Без инструментов на уровне ASIC вы мало что можете сделать. - person vermaete; 16.02.2013
comment
Ну, вы также можете написать несколько утверждений, чтобы проверить, проходит ли ваша симуляция все состояния в том порядке, в котором вы исключали. Это может помочь в более крупных проектах, когда основное внимание при написании кода и тестировании смещается от FSM. Если что-то пойдет не так в FSM, сообщение сделает отладку менее болезненной. - person vermaete; 16.02.2013
comment
Верди SpringSoft также может это сделать. - person ; 17.02.2013

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

person Martin Thompson    schedule 18.02.2013