#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