Регистр сдвига, подключение проводных входов к внутреннему регистру

#verilog

Вопрос:

Вот мой модуль

 module shift(
input clk,
input rstn,
input load, 
input dir,
input [7:0] LD,
output cout
);

reg [7:0] mem;

assign cout = dir?mem[0]:mem[7] ;


always @(posedge clk or negedge rstn)
begin
 if(!rstn)
  mem <= 8'h00;
 else begin
  if(load) 
   mem <= LD ;
  else mem <= mem ;
  case(dir)
   0 : mem <= mem<<1 ;
   1 : mem <= mem>>1 ;
  endcase
 end
end

endmodule   
 

а вот и мой испытательный стенд.

 module shift_tb();

reg clk;
reg rstn;
reg load;
reg dir;
reg[7:0] LD ;
wire cout;

shift UUT(.clk(clk), .rstn(rstn), .load(load), .dir(dir), .LD(LD), .cout(cout));

initial begin

$dumpfile("shift_out.vcd");
$dumpvars(2,shift_tb);

 clk = 0 ;
 rstn = 0 ;
 load = 0;
 dir = 0 ;
 LD = 8'h00;
 
 #10;
 rstn = 1;

 LD = 8'h55 ;
 load = 1;
 dir = 0 ;

 #100;

 LD = 8'hAA ;
 load = 1;
 dir = 1;

 #100;
 
 LD = 8'hFF;
 load = 1;
 rstn = 0 ;
 
 #20 ;
 $finish;
end 

always 
 #5 clk = ~clk ;

endmodule

 

В приведенном выше коде мой внутренний регистр «mem» не принимает значения из «LD» (параллельный ввод-вывод ).

Он остается на уровне 0. Код действительно сдвигается, если mem инициализируется случайным значением, скажем, 8’22, но все равно не учитывается LD .

Это содержит форму волны введите описание изображения здесь

Ответ №1:

Проблема в том, что у вас есть несколько активных неблокирующих назначений mem ; только одно должно быть активным в любой момент времени. После сброса у вас есть load =1 и dir =0. Это означает, что ваш код сначала присваивается mem <= LD , а затем немедленно присваивается mem <= mem<<1 . Вы не должны этого делать. Ваш код имеет case параллель с if оператором. Возможно, вы намеревались case , чтобы это было внутри else пункта.

 always @(posedge clk or negedge rstn) begin
    if(!rstn)
        mem <= 8'h00;
    else begin
        if(load) 
            mem <= LD ;
        else
            case(dir)
                0 : mem <= mem<<1;
                1 : mem <= mem>>1;
            endcase
    end
end
 

Когда я запускаю sim-карту, я вижу mem изменение на 'h55 , как и ожидалось.

В этом случае вам просто нужно LD высоко пульсировать в течение одного цикла в вашем тестовом стенде, вместо того, чтобы поддерживать его на высоком уровне все время:

  LD = 8'h55 ;
 load = 1;
 dir = 0 ;

 #10;
 load = 0;

 #100;
 

Ответ №2:

Вы использовали очень многословную логику. Попробуй это..

 always @(posedge clk or negedge rstn)
begin
if(!rstn)
  mem <= 8'h00;
else 
 mem <= (load)?LD:( dir ? mem>>1 : mem<<1 ); 
end
 

При туберкулезе используйте это. Переход сначала как 1->0->>1. Держите LD и нагрузку стабильной в течение 1
такта. Затем снимите нагрузку с утверждения.

 initial
begin
 clk = 1'd0;
 rst = 1'd1;
 load = 1'd0;
 dir = 1'd0;
 LD  = 'd0;

 #10  rst = 1'd0;
 #100 rst = 1'd1;
    load = 1'd1;
    LD = 8'h55;
 #10 load = 1'd0;

 end