RTL design (4)-RAM_to_AXIS flow control

AXIS flow control circuit structure

If the AXI-Stream communication protocol is used to output the data in RAM, without special processing, the data obtained after reading the RAM will be delayed by 1 cycle (if other processing is performed after reading, it may be delayed by 2 cycles or more) Many), this will cause the vallid signal to be interrupted.

In order to solve this problem and realize the AXI-Stream communication protocol to output the data in RAM without interruption , the following circuit structure is designed.

Insert picture description here

In the structure, a FIFO that automatically loads RAM data is used to achieve non-stop data transmission.
The write data pointer of FIFO is controlled by FIFO itself, and the read data pointer is controlled by AXIS.
When there is no data in the FIFO, it is automatically loaded from the RAM, so that every time AXI-Stream needs to transmit data, the data is ready and valid is always valid.

Circuit simulation model

The first half of the program is the initialization of ram data and clk and rst_n (LATCH==0: reading ram has a delay of 1 clock cycle), the middle part is the trigger logic, and the second half is the control logic of fifo and axis.

axis_flow.sv

`timescale 1ns / 1ps

// Company: 
// Engineer: 
// 
// Create Date: 2020/12/11
// Author Name: Sniper
// Module Name: axis_flow
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module axis_flow;

reg clk;
reg rst_n;

parameter LATCH = 0;
reg [7:0] ram_raddr;
reg [7:0] ram_rdata_buff;
reg [7:0] ram_rdata_buff2;
wire [7:0] ram_rdata;
reg ram_ren;

reg trigger;
reg m_axis_tvalid;
reg m_axis_tready;
wire [7:0] m_axis_tdata;
reg m_axis_tlast;


//clk gengrate
initial
begin
    clk = 1;
    forever #5 clk = ~clk;
end

//memory data init
reg [7:0] mem[255:0];
initial
begin
    for(int i=0;i<256;i=i+1)
        mem[i] = i;
end


//memory read control
always@(posedge clk)
begin
	if(ram_ren)
        {
    
    ram_rdata_buff2, ram_rdata_buff} <= {
    
    ram_rdata_buff, mem[ram_raddr]};
end
assign ram_rdata = LATCH? ram_rdata_buff2: ram_rdata_buff;


//m_axis_tready control
int percent = 00;
initial
begin
    m_axis_tready = 0;
    $srandom(100);//random seed
    forever @(posedge clk)
    begin
        m_axis_tready <= $urandom_range(99) >= percent;
    end
end


initial
begin
    rst_n = 0;
    trigger = 0;

    #100;
    rst_n = 1;

    repeat(10) @(posedge clk);
    @(posedge clk);
    trigger <= 1;
    @(posedge clk);
    trigger <= 0;

end


//auto-read fifo control
reg [7:0] ram_rdata_fifo[3:0];
reg [9:0] wr_ptr;
reg [9:0] rd_ptr;

reg ram_ren_buff;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
    begin
        ram_raddr <= 0;
        ram_ren <= 0;
        wr_ptr <= 0;
    end
	else
    begin
        if(wr_ptr <= rd_ptr + 3)
            ram_ren = 1;
        else
            ram_ren = 0;

        ram_ren_buff <= ram_ren;//delay 1 cycle get data
        if(ram_ren_buff)
        begin
            ram_rdata_fifo[wr_ptr[1:0]] <= ram_rdata;
            wr_ptr <= wr_ptr + 1;
            ram_raddr <= ram_raddr + 1;
        end

    end
end
assign m_axis_tdata = ram_rdata_fifo[rd_ptr[1:0]];


//axis output flow control
reg [7:0] state;
reg [9:0] out_cnt;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
    begin
        ram_raddr <= 0;
        m_axis_tvalid <= 0;
        m_axis_tlast <= 0;
        state <= 0;
        out_cnt <= 0;
        rd_ptr <= 0;
    end
	else
    begin
        case(state)
        0:
        begin
            if(trigger && (wr_ptr > rd_ptr + 3))
            begin
                rd_ptr <= 1;
                m_axis_tvalid <= 1;
                m_axis_tlast <= 0;
                out_cnt <= 0;
                state <= state + 1;
            end
        end
        1:
        begin
            if(m_axis_tvalid & m_axis_tready)
            begin
                rd_ptr <= rd_ptr + 1;

                out_cnt <= out_cnt + 1;
                if(out_cnt == 255 -1)
                    m_axis_tlast <= 1;
                else if(out_cnt == 255)
                begin
                    m_axis_tvalid <= 0;
                    m_axis_tlast <= 0;
                end
            end
        end

        default: state <= 0;
        endcase
    end
end




initial
begin
    $dumpfile("axis_flow.vcd");
    $dumpvars(0,axis_flow);
end

initial #5000 $finish;


endmodule

operation result

vcs -R -sverilog axis_flow.sv

m_axis_tvalid without interruption:
Insert picture description here

Ready adds randomness to verify the flow control function: it
Insert picture description here
Insert picture description here
can be seen that the output data is correct, there is a clock cycle delay for ram reading data, but the valid signal is always valid and the data is always ready.

Guess you like

Origin blog.csdn.net/meng1506789/article/details/111033020