#verilog #fsm
Вопрос:
Я пытаюсь создать конечный автомат , который обнаруживает 12-битный шаблон 110001010111
, но я не могу поставить галочку там, где она должна быть. Я добавил код, тестовый стенд и форму сигнала, которую я получил.
Код:
module seqdet (input clk,rst, input wire in, output reg y); parameter w=4'b0000,a=4'b0001,b=4'b0010,c=4'b0011,d=4'b0100,e=4'b0101,f=4'b0110,g=4'b0111, h=4'b1000,i=4'b1001,j=4'b1010,k=4'b1011,l=4'b1100; //wire in=Q; //assign in=Q[17:6];*/ reg [3:0] nst, st; always @ (posedge clk) begin if (rst) st lt;= w; else st lt;= nst; end always @ * begin nst =st; y = 1'b0; case(st) w: if(in) nst =a; a: if(in) nst =b; else nst =w; b: if(in) nst =b; else nst =c; c: if(in) nst =a; else nst =d; d: if(in) nst =a; else nst =e; e: if(in) nst =f; else nst =w; f: if(in) nst =b; else nst =g; g: if(in) nst =h; else nst =w; h: if(in) nst =b; else nst =i; i: if(in) nst =j; else nst =w; j:if(in) nst =k; else nst =w; k: if(in) nst =l; else nst =c; l: begin y=1'b1; if(in) nst =l; else nst =c; end default:nst =w; endcase end endmodule
Испытательный стенд:
`timescale 1ns / 1ns module fsm_detector_tb(); //declerations parameter T = 20; //clock period in nanoseconds reg clk, reset; reg test_input; wire test_tick; seqdet uut( .clk(clk), .rst(reset), .in(test_input), .y(test_tick) ); // clock // 20 ns clock running forever always begin clk = 1'b1; //high #(T/2); // delay half a period clk = 1'b0; //low #(T/2); // delay half a period end initial begin // reset = 1'b1; // test_input = 1'b0; // #(2*T); // delay two clock cycle reset = 1'b0; test_input = 1'b1; #(T); // delay one clock cycle test_input = 1'b1; #(T); // delay one clock cycle test_input = 1'b0; #(T); // delay one clock cycle test_input = 1'b0; #(T); // delay one clock cycle test_input = 1'b0; #(T); // delay one clock cycle test_input = 1'b1; #(T); // delay one clock cycle test_input = 1'b0; #(T); // delay one clock cycle test_input = 1'b1; #(T); // delay one clock cycle test_input = 1'b0; #(T); // delay one clock cycle test_input = 1'b1; #(T); test_input = 1'b1; #(T); test_input = 1'b1; #(T); $finish; end endmodule
Выход должен быть высоким там, где он отмечен на форме сигнала, и я не могу понять, где это пошло не так.
Комментарии:
1.
b: if(in) nst = b; else nst = c;
— можете ли вы объяснить, почему вы считаете это правильным?2. Где это
st
в симуляции?
Ответ №1:
Проблема в тестовом стенде. Входы неправильно синхронизированы с часами. Вы должны управлять входными данными в тестовой среде так же, как вы управляете ими внутри кода разработки: используйте @(posedge clk)
и неблокирующие назначения ( lt;=
) вместо #
задержек и блокировок назначений. Замените свой initial
блок следующим:
initial begin reset = 1; test_input = 0; repeat (2) @(posedge clk); reset lt;= 0; @(posedge clk) test_input lt;= 1; @(posedge clk) test_input lt;= 1; @(posedge clk) test_input lt;= 0; @(posedge clk) test_input lt;= 0; @(posedge clk) test_input lt;= 0; @(posedge clk) test_input lt;= 1; @(posedge clk) test_input lt;= 0; @(posedge clk) test_input lt;= 1; @(posedge clk) test_input lt;= 0; @(posedge clk) test_input lt;= 1; @(posedge clk) test_input lt;= 1; @(posedge clk) test_input lt;= 1; repeat (3) @(posedge clk); $finish; end
Это гарантирует, что симулятор будет работать так, как ожидалось. Я вижу test_tick
, что поднимаюсь высоко, когда ты этого ожидаешь.
Этот код также утверждает сброс во время 0, а затем выпускает его через пару циклов, что гарантирует, что ваш дизайн будет сброшен правильно.