0
votes

How do you use the read enable to properly output a signal on a pin? I am using a ZyBo board and used a the FIFO Generator Wizard. I need an asynchronous, continuous writing to a FIFO and reading from the FIFO. This is why I need a write_enable signal and read_enable signal. However, I cannot read from the FIFO. I check to make sure the FIFO isn't empty and that read_enable is asserted. I read from the FIFO by serializing a 32bit word onto a data pin. (It alternates from serializing onto pin I and pin Q). How can I make sure I am reading from the FIFO and outputting the serialized data onto a pin? The following is my code:

// 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

Thanks in advance for all the help

1

1 Answers

0
votes

You need to design a bit better the way you write your clocked logic.

For example, in your code, you only write to I and Q if the fifo is not empty, which is not correct.

You need a module which:

  • Takes in a 32-bit value from the fifo, stores it, and then serializes it out to a pin over 32 cycles.
  • Once a value has been read in from the fifo, it needs to keep serializing regardless of whether or not the fifo is empty (you only care about the state of the fifo when you're pulling in a new 32-bit value).
  • Only accepts a new value when it is not currently doing serialization.

The design looks to be making progress since your last question, but you haven't got the logic right yet. Try using a waveform debugger to understand better why it's not working the way you expect.