Мастер асинхронного FIFO verilog

#verilog #fifo

#verilog #fifo

Вопрос:

Как вы используете разрешение чтения для правильного вывода сигнала на вывод? Я использую плату ZyBo и использовал мастер генератора FIFO. Мне нужна асинхронная непрерывная запись в FIFO и чтение из FIFO. Вот почему мне нужен сигнал write_enable и сигнал read_enable. Однако я не могу читать из FIFO. Я проверяю, чтобы убедиться, что FIFO не пуст и что read_enable утверждается. Я читаю из FIFO, сериализуя 32-битное слово в вывод данных. (Он чередуется с сериализацией на вывод I и вывод Q). Как я могу убедиться, что я читаю из FIFO и выводю сериализованные данные на PIN-код? Ниже приведен мой код:

 // 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 amp;amp; 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 amp;amp; !capture_full amp;amp; 
             !capture_has_been_full amp;amp;
             (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 amp;amp; 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 amp;amp; 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
 

Заранее спасибо за всю помощь

Ответ №1:

Вам нужно немного улучшить способ написания вашей логики с тактовой частотой.

Например, в вашем коде вы записываете в I и Q только в том случае, если fifo не является пустым, что неверно.

Вам нужен модуль, который:

  • Принимает 32-разрядное значение из fifo, сохраняет его, а затем сериализует его в вывод в течение 32 циклов.
  • После считывания значения из fifo оно должно продолжать сериализацию независимо от того, является ли fifo пустым (вы заботитесь о состоянии fifo только тогда, когда вводите новое 32-разрядное значение).
  • Принимает новое значение только тогда, когда оно в данный момент не выполняет сериализацию.

С момента вашего последнего вопроса дизайн, похоже, продвигается вперед, но у вас еще нет правильной логики. Попробуйте использовать отладчик сигналов, чтобы лучше понять, почему он работает не так, как вы ожидаете.

Комментарии:

1. Я знаю, что использование отладчика сигналов было бы лучшим способом увидеть, что не так с моей логикой. Однако я использовал генератор FIFO, и при попытке смоделировать мой код я получаю следующую ошибку: СБОЙ: поведенческие модели для встроенных конфигураций FIFO Virtex-4, Virtex-5, Virtex-6 и 7-Series FPGA в настоящее время не поддерживаются.