Я пытаюсь выучить правильное / готовое рукопожатие в verilog.В частности, мне интересно использовать флаг ready в качестве флага, который указывает на успешную транзакцию данных (т. Е. ready_in
становится высоким после того, как valid_out
становится высоким).Я хотел бы объяснить мою проблему на очень простом примере Verilog.Я написал сверточный кодер (код ниже)
module Conv_Encoder_Core(
input wire clk,
input wire reset,
input wire in_bit,
output reg out_A,
output reg out_B,
input wire sleep,
input wire valid_in,
input wire ready_in,
output reg valid_out,
output reg ready_out);
reg [5:0] S;
wire S_A, S_B, clkON;
assign S_A = S[1] ^ S[2] ^ S[4] ^S[5];
assign S_B = S[0] ^ S[1] ^ S[2] ^S[5];
assign clkON = clk & !sleep;
always @(posedge clkON)begin
if (reset) begin
S <=0;
valid_out <=0;
ready_out <=0;
end else if (valid_in) begin
out_A <= in_bit ^ S_A;
out_B <= in_bit ^ S_B;
valid_out <=1;
if (ready_in)begin
S<= S<<1;
S[0] <=in_bit;
ready_out <=1;
end else begin
ready_out <=0;
end
end else begin
valid_out <=0;
ready_out <=0;
end
end
endmodule
Мне интересно использовать флаг ready_in
в качестве индикатора того, что данные out_A
и out_B
получены следующим блоком, поэтому мой блокможете принять новые данные, установив флаг ready_out
.Я написал тестовый стенд для этого блока, однако я не получаю ожидаемых результатов
`timescale 1 ns/1 ns
module TB_Conv();
reg clk;
//---------------clock generator-----------------------
initial begin
clk = 1'b0;
#5;
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
//------------------ dump -----------------------
initial begin
$dumpfile("dumpVCD.vcd");
$dumpvars(10);
end
localparam N_DATA=10;
reg in_bits_vec [0:N_DATA-1];
initial begin
in_bits_vec[0] = 1'b1;
in_bits_vec[1] = 1'b0;
in_bits_vec[2] = 1'b0;
in_bits_vec[3] = 1'b0;
in_bits_vec[4] = 1'b0;
in_bits_vec[5] = 1'b0;
in_bits_vec[6] = 1'b0;
in_bits_vec[7] = 1'b0;
in_bits_vec[8] = 1'b0;
in_bits_vec[9] = 1'b1;
end
reg in_bit, ready_in,reset, valid_in;
Conv_Encoder_Core UUT(.clk(clk),
.reset(reset),
.in_bit(in_bit),
.out_A(out_A),
.out_B(out_B),
.sleep(1'b0),
.valid_in(valid_in),
.ready_in(ready_in),
.valid_out(valid_out),
.ready_out(ready_out));
//---------------- code starts here -------------------//
reg [3:0] addr;
always @(posedge clk) begin
if (reset)begin
addr<=0;
valid_in <=0;
in_bit <=0;
end else if (addr < 10) begin
in_bit <= in_bits_vec[addr];
valid_in <=1'b1;
if (ready_out) begin
addr <= addr+1'b1;
end
end else begin
in_bit <=0;
valid_in <=0;
end
if (valid_out==1) ready_in <= 1;
else ready_in <= 0;
end
// ----------- reset logic -----------//
reg [3:0] cnt;
initial cnt=0;
always @(negedge clk)begin
if (cnt<5) begin
reset = 1;
cnt=cnt+1;
end else reset =0;
end
initial begin
#1000;
$finish;
end
endmodule
Если вы посмотрите на входные данные (в тестовом бекче), вы увидите, что это 1000000000
,Я ожидаю увидеть, как 1
будет проходить через регистр S
следующим образом:
S = 000000 //at beginning
S = 000001 // after ready_out=1
S = 000010
S = 000100
однако результаты, которые я получаю, совершенно другие (см. Снимок экрана).Другая проблема, с которой я столкнулся, заключается в том, что inbit=1
продолжает на два такта больше, чем я ожидаю.на самом деле, когда ready_out=1
, я ожидаю увидеть, что in_bit
станет равным нулю, но это происходит через два такта (желтый курсор на снимке).
Я был бы очень признателен, если бы кто-то мог объяснить, что я делаюнеправильно в этом примере.