Verilog中的有效就绪握手
我正在努力学习verilog中的有效/准备握手。特别是,我有兴趣使用ready作为一个标志,指示数据的成功事务(即,Verilog中的有效就绪握手,verilog,system-verilog,hdl,Verilog,System Verilog,Hdl,我正在努力学习verilog中的有效/准备握手。特别是,我有兴趣使用ready作为一个标志,指示数据的成功事务(即,valid\u out变高后,ready\u In变高)。我想用一个非常简单的Verilog示例来解释我的问题。我已经写了一个卷积编码器(代码如下) 如果查看输入数据(在testbech中),可以看到它是100000000。我希望看到1通过S寄存器传递,如下所示: S = 000000 //at beginning S = 000001 // after ready_out=1 S
valid\u out
变高后,ready\u In
变高)。我想用一个非常简单的Verilog示例来解释我的问题。我已经写了一个卷积编码器(代码如下)
如果查看输入数据(在testbech中),可以看到它是100000000
。我希望看到1
通过S
寄存器传递,如下所示:
S = 000000 //at beginning
S = 000001 // after ready_out=1
S = 000010
S = 000100
但是,我得到的结果完全不同(请参见快照)。
我遇到的另一个问题是inbit=1
比我预期的持续两个时钟周期。事实上,当ready\u out=1
时,我希望看到in\u bit
变为零,但这会在两个时钟周期后发生(快照中的黄色光标)
如果有人能解释一下我在这个例子中做错了什么,我将不胜感激
Conv_编码器_核心
模块转换编码器核心
(
输入线时钟,
输入线复位,
_位中的输入线,
输出reg out_A,
输出reg out_B,
输入线睡眠,
//输入通道
输入线inp_有效_i,
输出线inp\U就绪\U o,
//输出通道
输出reg out\u有效\u o,
输入reg out\u就绪\u i
);
reg[5:0]S;
电线S_A、S_B、clkON;
分配S_A=S[1]^S[2]^S[4]^S[5];
分配S_B=S[0]^S[1]^S[2]^S[5];
分配clkON=clk&!睡觉
//--更改从这里开始--//
电线;
注册完全注册;
分配wr_en=~full_r|out_ready_i;
始终@(posedge clkON)开始
如果(重置)开始
s
`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
S = 000000 //at beginning
S = 000001 // after ready_out=1
S = 000010
S = 000100
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 channel
input wire inp_valid_i,
output wire inp_ready_o,
// output channel
output reg out_valid_o,
input reg out_ready_i
);
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;
// -- Changes start here -- //
wire wr_en;
reg full_r;
assign wr_en = ~full_r | out_ready_i;
always @(posedge clkON)begin
if (reset) begin
S <=0;
full_r <=0;
end else begin
if (wr_en) begin
if (inp_valid_i) begin
full_r <= 1;
out_A <= in_bit ^ S_A;
out_B <= in_bit ^ S_B;
S <= S<<1;
S[0] <=in_bit;
end else begin
full_r <= 0;
end
end
end
end
assign inp_ready_o = wr_en;
assign out_valid_o = full_r;
endmodule
`timescale 1 ns/1 ns
module tb();
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, reset, inp_valid, inp_ready, out_valid, out_ready;
Conv_Encoder_Core UUT(.clk(clk),
.reset(reset),
.in_bit(in_bit),
.out_A(out_A),
.out_B(out_B),
.sleep(1'b0),
// input channel
.inp_valid_i(inp_valid),
.inp_ready_o(inp_ready),
// output channel
.out_valid_o(out_valid),
.out_ready_i(out_ready));
//---------------- code starts here -------------------//
reg [3:0] addr;
// -- Transmitter Side -- //
always @(posedge clk) begin: ff_addr
if (reset)begin
addr <= 0;
end else begin
if (addr < 10) begin
if (inp_valid && inp_ready) begin
addr <= addr + 1;
end
end else begin
addr <= 0;
end
end
end
assign inp_valid = (addr < 10) ? 1'b1 : 1'b0;
assign in_bit = in_bits_vec[addr];
// -- Receiver Side -- //
always @(posedge clk) begin: ff_ready_in
if (reset) begin
out_ready <= 0;
end else begin
out_ready <= $urandom_range(0, 1); // some randomness on the receiver, otherwise, we won't see if our DUT behaves correctly in case of ready=0
end
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