verilog异步FIFO向导
如何使用读取启用在引脚上正确输出信号?我使用的是ZyBo板和FIFO生成器向导。我需要一个异步,连续写入到FIFO和读取从FIFO。这就是为什么我需要一个写启用信号和读启用信号。但是,我无法从FIFO读取数据。我检查以确保FIFO不是空的,并且已断言读取启用。我通过将32位字串行化到数据管脚上读取FIFO。(它交替从串行化到引脚I和引脚Q)。如何确保读取FIFO并将序列化数据输出到pin上?以下是我的代码:verilog异步FIFO向导,verilog,fifo,Verilog,Fifo,如何使用读取启用在引脚上正确输出信号?我使用的是ZyBo板和FIFO生成器向导。我需要一个异步,连续写入到FIFO和读取从FIFO。这就是为什么我需要一个写启用信号和读启用信号。但是,我无法从FIFO读取数据。我检查以确保FIFO不是空的,并且已断言读取启用。我通过将32位字串行化到数据管脚上读取FIFO。(它交替从串行化到引脚I和引脚Q)。如何确保读取FIFO并将序列化数据输出到pin上?以下是我的代码: // Wires and registers related to data captu
// Wires and registers related to data capturing
wire capture_clk;
reg [31:0] capture_data;
wire capture_en;
reg [4:0] slowdown;
wire capture_full;
reg capture_open;
reg capture_open_cross;
reg capture_has_been_full;
reg capture_has_been_nonfull;
reg has_been_full_cross;
reg has_been_full;
// Data capture section
// ====================
always @(posedge capture_clk)
begin
if (capture_en)
capture_data <= user_w_write_32_data; // Data source being read from a file
// The slowdown register limits the data pace to 1/32 the bus_clk
// when capture_clk = bus_clk. This is necessary, because the
// core in the evaluation kit is configured for simplicity, and
// not for performance. Sustained data rates of 200 MB/sec are
// easily reached with performance-oriented setting.
// The slowdown register has no function in a real-life application.
slowdown <= slowdown + 1;
// capture_has_been_full remembers that the FIFO has been full
// until the file is closed. capture_has_been_nonfull prevents
// capture_has_been_full to respond to the initial full condition
// every FIFO displays on reset.
if (!capture_full)
capture_has_been_nonfull <= 1;
else if (!capture_open)
capture_has_been_nonfull <= 0;
if (capture_full && capture_has_been_nonfull)
capture_has_been_full <= 1;
else if (!capture_open)
capture_has_been_full <= 0;
end
// The dependency on slowdown is only for bogus data
assign capture_en = capture_open && !capture_full &&
!capture_has_been_full &&
(slowdown == 0);
// Clock crossing logic: bus_clk -> capture_clk
always @(posedge capture_clk)
begin
capture_open_cross <= user_r_read_32_open;
capture_open <= capture_open_cross;
end
// Clock crossing logic: capture_clk -> bus_clk
always @(posedge bus_clk)
begin
has_been_full_cross <= capture_has_been_full;
has_been_full <= has_been_full_cross;
end
// The user_r_read_32_eof signal is required to go from '0' to '1' only on
// a clock cycle following an asserted read enable, according to Xillybus'
// core API. This is assured, since it's a logical AND between
// user_r_read_32_empty and has_been_full. has_been_full goes high when the
// FIFO is full, so it's guaranteed that user_r_read_32_empty is low when
// that happens. On the other hand, user_r_read_32_empty is a FIFO's empty
// signal, which naturally meets the requirement.
assign user_r_read_32_eof = user_r_read_32_empty && has_been_full;
assign user_w_write_32_full = 0;
// The data capture clock here is bus_clk for simplicity, but clock domain
// crossing is done properly, so capture_clk can be an independent clock
// without any other changes.
assign capture_clk = bus_clk;
async_fifo_32x512 fifo_32 //FIFO created using Xilinx FIFO Generator Wizard
(
.rst(!user_r_read_32_open),
.wr_clk(capture_clk),
.rd_clk(bus_clk),
.din(capture_data),
.wr_en(capture_en),
.rd_en(user_r_read_32_rden),
.dout(user_r_read_32_data),
.full(capture_full),
.empty(user_r_read_32_empty)
);
reg Q_en = 1'b0; //starting value is 0 because first 32bit is I
reg [31:0] data_outI = 32'd0;
reg [31:0] data_outQ = 32'd0;
reg I = 1'b0;
reg Q = 1'b0;
reg counter_32_shift = 6'b000000;
reg temp = 1'b0;
always @(posedge bus_clk) begin
if(user_r_read_32_empty == 1'b0 && user_r_read_32_rden == 1'b1)begin //if something in FIFO
if(Q_en == 1'b0) begin //output onto pin I
if(counter_32_shift == 6'b000000) begin
data_outI <= user_r_read_32_data;
end else if(counter_32_shift != 5'd32) begin
I <= data_outI[0];
data_outI <= (data_outI >> 1);
Q <= data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= counter_32_shift + 1'b1;
end else begin //counter_32_shift == 32
I <= data_outI[0];
data_outI <= (data_outI >> 1);
Q <= data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= 6'd0;
Q_en <= ~Q_en;
end
end else if(Q_en == 1'b1) begin //Output onto pin Q
if(counter_32_shift == 6'd0) begin
data_outQ <= user_r_read_32_data;
end else if(counter_32_shift != 6'd32) begin
I <= data_outI[0];
data_outI <= (data_outI >> 1);
Q <= data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= counter_32_shift + 1'b1;
end else begin //counter_32_shift == 32
I = data_outI[0];
data_outI <= (data_outI >> 1);
Q = data_outQ[0];
data_outQ <= (data_outQ >> 1);
counter_32_shift <= 6'd0;
Q_en <= ~Q_en;
end
end// end Q_en compare
end //end check if FIFO empty
end //end always
//与数据捕获相关的连线和寄存器
有线电视;
reg[31:0]捕获_数据;
线俘获;
reg[4:0]减速;
线俘获;
注册捕获开放;
注册捕获\开放\交叉;
注册捕获已满;
注册捕获已被取消;
注册已满;
注册已满;
//数据捕获科
// ====================
始终@(posedge捕获时钟)
开始
如果(捕获)
捕获数据您需要设计更好的时钟逻辑编写方式
例如,在您的代码中,如果fifo不为空,则只写入I和Q,这是不正确的
您需要一个模块,该模块:
- 从fifo接收32位值,存储它,然后在32个周期内将其序列化为一个引脚李>
- 一旦从fifo中读入一个值,无论fifo是否为空,它都需要继续序列化(当您读入一个新的32位值时,您只关心fifo的状态)
- 仅在当前未执行序列化时接受新值
从上一个问题开始,该设计看起来正在取得进展,但您还没有掌握正确的逻辑。尝试使用波形调试器来更好地理解为什么它不能按预期的方式工作 我知道使用波形调试器是查看我的逻辑有什么问题的最好方法。但是,我使用了FIFO生成器,在尝试模拟代码时出现以下错误:失败:目前不支持Virtex-4、Virtex-5、Virtex-6和7系列FPGA的内置FIFO配置的行为模型。