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.
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:
Ready adds randomness to verify the flow control function: it
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.