Как мне посчитать определенную последовательность c в Verilog? - PullRequest
0 голосов
/ 20 июня 2020

Мне нужно разработать схему, которая может считать 1011 в последовательности битов. Например, если последовательность показана на рисунке, счет должен быть 1, но это не так. Я знаю, что читаю ввод w не последовательно, но я тоже не знаю, как это сделать.

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

picture of circuit

картина государственных автоматов. второй - то, что я использовал

основной лог c:

module serialCounter(w,clk,resetn,z);
input w,clk,resetn;
output reg z;
reg [2:0] CS,NS;
reg [7:0] count;
parameter S0=3'b000, S1=3'b001, S2=3'b010, S3=3'b011, S4=3'b100;
always @(w,CS)
  case(CS)
    S0:if(w==1)
    begin
      NS=S1;
    end
       else
    begin
      NS=S0;
    end
    S1:if(w==1)
    begin
      NS=S2;
    end
       else
    begin
      NS=S0;
    end
    S2:if(w==1)
    begin
      NS=S2;
    end
       else
    begin
      NS=S3;
    end
    S3:if(w==1)
    begin
      NS=S4; 
    end
       else
    begin
      NS=S0;
    end
    S4:begin NS=S0;end
endcase

always @(posedge clk, negedge resetn)
begin
  if(resetn == 0)
    CS<=S0;
  else
    CS<=NS;
end
always @(CS) 
begin
  if(CS==S4)
    begin 
      z=1;
      count<=count+1;
    end
end
endmodule


тестовая среда:

`timescale 1ns/1ns
module counterTB();
reg w,clk,resetn;
reg [2:0] CS,NS;
wire z;
wire [7:0] count;
integer i;
serialCounter sk(.w(w),.clk(clk),.resetn(resetn),.z(z));
initial
  begin
    resetn = 1'b0;
    clk = 1'b0;
    CS=3'b000;
  end
initial
begin
  for(i=0;i<255;i=i+1)
    @(posedge clk, negedge resetn)  w=i;
end
always #5 clk = ~clk;


always @(posedge clk, negedge resetn) $monitor("w=%b, z=%b, count=%d", w,z,count);

endmodule

Ответы [ 3 ]

1 голос
/ 20 июня 2020

Есть несколько проблем.

Вы заявили о сбросе, но так и не выпустили его (resetn остается на 0). Вам нужно установить его в 1 после нескольких тактов.

Вам нужно по-другому управлять вводом w в тестовой среде. Ваш проект всегда делает выборку, когда он равен 0. Один из быстрых способов - запустить его в случайном порядке.

Вы неправильно смоделировали выход z, который, как я полагаю, является вашим сигналом "обнаружения". Я также удалил count logi c из этого блока always, поскольку он, похоже, не делал ничего важного.

Вот код, который теперь запускается и обнаруживает шаблон 1011 на w:

module serialCounter(w,clk,resetn,z);
input w,clk,resetn;
output reg z;
reg [2:0] CS,NS;
reg [7:0] count;
parameter S0=3'b000, S1=3'b001, S2=3'b010, S3=3'b011, S4=3'b100;
always @(w,CS)
  case(CS)
    S0:if(w==1)
    begin
      NS=S1;
    end
       else
    begin
      NS=S0;
    end
    S1:if(w==1)
    begin
      NS=S2;
    end
       else
    begin
      NS=S0;
    end
    S2:if(w==1)
    begin
      NS=S2;
    end
       else
    begin
      NS=S3;
    end
    S3:if(w==1)
    begin
      NS=S4; 
    end
       else
    begin
      NS=S0;
    end
    S4:begin NS=S0;end
endcase

always @(posedge clk, negedge resetn)
begin
  if(resetn == 0)
    CS<=S0;
  else
    CS<=NS;
end

always @* begin
  if(CS==S4) begin 
        z=1;
  end else begin
        z=0;
  end
end

endmodule



module counterTB();
reg w,clk,resetn;
reg [2:0] CS,NS;
wire z;
wire [7:0] count;
integer i;
serialCounter sk(.w(w),.clk(clk),.resetn(resetn),.z(z));

initial
  begin
    resetn = 1'b0;
    clk = 1'b0;
    CS=3'b000;
    #30 resetn=1;
    #5000 $finish;
  end

always #5 clk = ~clk;

always @(posedge clk, negedge resetn) $monitor("w=%b, z=%b, count=%d", w,z,count);

always @(posedge clk, negedge resetn) begin
    w <= $random;
end

endmodule
0 голосов
/ 21 июня 2020

Думаю, есть более простой способ создать этот конечный автомат. В следующем примере reg [3:0] регистр шаблона, который хранит 4 бита шаблона. Затем он просто сравнивает шаблон с желаемым (в данном случае seq).

module serialCounter(w, clk, resetn, z, counter);
    input w, clk, resetn;
    output reg z;
    output reg[7:0] counter;
  
  reg[3:0] pattern, tmp;
  parameter seq = 4'b1011;
  
  always@(posedge clk) begin
    if (!resetn) begin
      pattern <= 0;
      counter <= 0;
    end
    else begin
      tmp = (pattern << 1) | w;
      
      if (tmp == seq) begin
        counter <= counter + 1;
        z <= 1;
      end
      else
        z <= 0;
      
      pattern <= tmp;
    end
  end   
endmodule
  
module counterTB();
   reg w,clk,resetn;
   reg [2:0] CS,NS;
   wire z;
   reg [7:0] count;

  integer i;
  serialCounter sk(.w(w), .clk(clk), .resetn(resetn), .z(z), .counter(count));

initial
  begin
    resetn = 1'b0;
    clk = 1'b0;
    CS=3'b000;
    #30 resetn=1;
    #5000 $finish;
  end

always #5 clk = ~clk;

  initial $monitor("clk=%b, w=%b, z=%b, count=%d pattern=%b", clk, w,z, count, sk.pattern);

initial begin
  w = 0;
  forever #10 w = $random;
end
  
endmodule

Я также исправил пару вещей в модуле tb, например, $ monitor следует использовать в начальном блоке. Я также изменил способ генерации w.

0 голосов
/ 20 июня 2020

Были внесены некоторые исправления в код, во-первых, мы должны избавиться от предполагаемых защелок в основных логах c (z и count), заканчивались так:

module serialCounter(w,clk,resetn,z);
input w,clk,resetn;
output reg z;
reg [2:0] CS,NS;
reg [7:0] count;
parameter S0=3'b000, S1=3'b001, S2=3'b010, S3=3'b011, S4=3'b100;
always @(w,CS)
  case(CS)
    S0:if(w==1)
    begin
      NS=S1;
    end
       else
    begin
      NS=S0;
    end
    S1:if(w==1)
    begin
      NS=S2;
    end
       else
    begin
      NS=S0;
    end
    S2:if(w==1)
    begin
      NS=S2;
    end
       else
    begin
      NS=S3;
    end
    S3:if(w==1)
    begin
      NS=S4;
    end
       else
    begin
      NS=S0;
    end
    S4:begin NS=S0;end
    default: NS=S0;
endcase

always @(posedge clk, negedge resetn)
begin
  if(resetn == 0)
    CS<=S0;
  else
    CS<=NS;
end
always @(posedge clk, negedge resetn)
begin
  if(resetn == 0)
    begin
      z<=0;
      count<=0;
    end
  if(CS==S4)
    begin
      z<=1;
      count<=count+1;
    end
end
endmodule

Во-вторых, в модуль тестового стенда, resetn никогда не менялся с 0 на 1, так как у нас есть асинхронный сброс с активным низким уровнем, он всегда был в состоянии сброса, также, если вы установите "w" с младшим битом счетчика, он будет переключался каждый цикл. Я изменил его на сдвинутый регистр с битовым счетчиком. Тестовый стенд работал следующим образом:

`timescale 1ns/1ns
module counterTB();
localparam WIDTH = 8;
reg clk,resetn;
reg [2:0] CS,NS;
wire w;
wire z;
wire [WIDTH-1:0] count;
reg  [WIDTH-1:0] w_reg;
reg  [WIDTH-1:0] w_nxt;
reg  [$clog2(WIDTH)-1:0] bit_count;
integer i;
serialCounter sk(.w(w),.clk(clk),.resetn(resetn),.z(z));
initial
  begin
    resetn = 1'b0;
    clk = 1'b0;
    CS=3'b000;
    w_reg = 0;
    w_nxt = 0;
  end

//DISABLE RESET
always #10 resetn = 1'b1;

always @ (posedge clk, negedge resetn) begin
  if(resetn == 0) begin
    w_reg <= 0;
    w_nxt <= 1;
    bit_count <= 0;
  end
  else begin
    if(bit_count == (WIDTH-1)) begin
      if(&w_nxt) begin
        $finish;
      end
      else begin
        w_reg <= w_nxt;
        w_nxt <= w_nxt + 1;
        bit_count <= 0;
      end
    end
    else begin
      w_reg <= w_reg >> 1;
      bit_count <= bit_count + 1;
    end
  end
end

assign w = w_reg[0];

always #5 clk = ~clk;

always @(posedge clk, negedge resetn) $monitor("w=%b, z=%b, count=%d, w_reg=%x, w_nxt=%h, bit_count=%d, reset=%b", w,z,sk.count,w_reg,w_nxt,bit_count,resetn);

endmodule

Последняя часть результатов моделирования (считается до 255):

w=0, z=1, count=104, w_reg=fa, w_nxt=fb, bit_count=0, reset=1
w=1, z=1, count=104, w_reg=7d, w_nxt=fb, bit_count=1, reset=1
w=0, z=1, count=104, w_reg=3e, w_nxt=fb, bit_count=2, reset=1
w=1, z=1, count=105, w_reg=1f, w_nxt=fb, bit_count=3, reset=1
w=1, z=1, count=105, w_reg=0f, w_nxt=fb, bit_count=4, reset=1
w=1, z=1, count=105, w_reg=07, w_nxt=fb, bit_count=5, reset=1
w=1, z=1, count=105, w_reg=03, w_nxt=fb, bit_count=6, reset=1
w=1, z=1, count=105, w_reg=01, w_nxt=fb, bit_count=7, reset=1
w=1, z=1, count=105, w_reg=fb, w_nxt=fc, bit_count=0, reset=1
w=1, z=1, count=105, w_reg=7d, w_nxt=fc, bit_count=1, reset=1
w=0, z=1, count=105, w_reg=3e, w_nxt=fc, bit_count=2, reset=1
w=1, z=1, count=105, w_reg=1f, w_nxt=fc, bit_count=3, reset=1
w=1, z=1, count=105, w_reg=0f, w_nxt=fc, bit_count=4, reset=1
w=1, z=1, count=106, w_reg=07, w_nxt=fc, bit_count=5, reset=1
w=1, z=1, count=106, w_reg=03, w_nxt=fc, bit_count=6, reset=1
w=1, z=1, count=106, w_reg=01, w_nxt=fc, bit_count=7, reset=1
w=0, z=1, count=106, w_reg=fc, w_nxt=fd, bit_count=0, reset=1
w=0, z=1, count=106, w_reg=7e, w_nxt=fd, bit_count=1, reset=1
w=1, z=1, count=106, w_reg=3f, w_nxt=fd, bit_count=2, reset=1
w=1, z=1, count=106, w_reg=1f, w_nxt=fd, bit_count=3, reset=1
w=1, z=1, count=106, w_reg=0f, w_nxt=fd, bit_count=4, reset=1
w=1, z=1, count=106, w_reg=07, w_nxt=fd, bit_count=5, reset=1
w=1, z=1, count=106, w_reg=03, w_nxt=fd, bit_count=6, reset=1
w=1, z=1, count=106, w_reg=01, w_nxt=fd, bit_count=7, reset=1
w=1, z=1, count=106, w_reg=fd, w_nxt=fe, bit_count=0, reset=1
w=0, z=1, count=106, w_reg=7e, w_nxt=fe, bit_count=1, reset=1
w=1, z=1, count=106, w_reg=3f, w_nxt=fe, bit_count=2, reset=1
w=1, z=1, count=106, w_reg=1f, w_nxt=fe, bit_count=3, reset=1
w=1, z=1, count=107, w_reg=0f, w_nxt=fe, bit_count=4, reset=1
w=1, z=1, count=107, w_reg=07, w_nxt=fe, bit_count=5, reset=1
w=1, z=1, count=107, w_reg=03, w_nxt=fe, bit_count=6, reset=1
w=1, z=1, count=107, w_reg=01, w_nxt=fe, bit_count=7, reset=1
w=0, z=1, count=107, w_reg=fe, w_nxt=ff, bit_count=0, reset=1
w=1, z=1, count=107, w_reg=7f, w_nxt=ff, bit_count=1, reset=1
w=1, z=1, count=107, w_reg=3f, w_nxt=ff, bit_count=2, reset=1
w=1, z=1, count=108, w_reg=1f, w_nxt=ff, bit_count=3, reset=1
w=1, z=1, count=108, w_reg=0f, w_nxt=ff, bit_count=4, reset=1
w=1, z=1, count=108, w_reg=07, w_nxt=ff, bit_count=5, reset=1
w=1, z=1, count=108, w_reg=03, w_nxt=ff, bit_count=6, reset=1
w=1, z=1, count=108, w_reg=01, w_nxt=ff, bit_count=7, reset=1
w=1, z=1, count=108, w_reg=01, w_nxt=ff, bit_count=7, reset=1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...