function integer log2;
    input integer x;
    integer n, m;
begin
    n = 0;
    m = 1;
    while (m < x) begin
        n = n + 1;
        m = m * 2;
    end
    log2 = n;
end
endfunction

'Programming > Verilog' 카테고리의 다른 글

AXI Buffer  (1) 2020.04.04
AXI FIFO  (0) 2020.02.13
AXI Register Slice  (0) 2020.02.12
Verilog Generate  (2) 2018.07.05
Xilinx bootgen  (0) 2017.06.21
module example_a_m_axi_fifo
#(parameter
    DATA_BITS  = 8,
    DEPTH      = 16,
    DEPTH_BITS = 4
)(
    input  wire                 sclk,
    input  wire                 reset,
    input  wire                 sclk_en,
    output reg                  empty_n,
    output reg                  full_n,
    input  wire                 rdreq,
    input  wire                 wrreq,
    output reg  [DATA_BITS-1:0] q,
    input  wire [DATA_BITS-1:0] data
);
//------------------------Parameter----------------------

//------------------------Local signal-------------------
wire                  push;
wire                  pop;
wire                  full_cond;
reg                   data_vld;
reg  [DEPTH_BITS-1:0] pout;
reg  [DATA_BITS-1:0]  mem[0:DEPTH-1];
//------------------------Body---------------------------
assign push = full_n & wrreq;
assign pop  = data_vld & (~(empty_n & ~rdreq));
if (DEPTH >= 2) begin
assign full_cond = push && ~pop && pout == DEPTH - 2 && data_vld;
end else begin
assign full_cond = push && ~pop;
end

// q
always @(posedge sclk)
begin
    if (reset)
        q <= 0;
    else if (sclk_en) begin
        if (~(empty_n & ~rdreq))
            q <= mem[pout];
    end
end

// empty_n
always @(posedge sclk)
begin
    if (reset)
        empty_n <= 1'b0;
    else if (sclk_en) begin
        if (~(empty_n & ~rdreq))
            empty_n <= data_vld;
    end
end

// data_vld
always @(posedge sclk)
begin
    if (reset)
        data_vld <= 1'b0;
    else if (sclk_en) begin
        if (push)
            data_vld <= 1'b1;
        else if (~push && pop && pout == 1'b0)
            data_vld <= 1'b0;
    end
end

// full_n
always @(posedge sclk)
begin
    if (reset)
        full_n <= 1'b1;
    else if (sclk_en) begin
        if (pop)
            full_n <= 1'b1;
        else if (full_cond)
            full_n <= 1'b0;
    end
end

// pout
always @(posedge sclk)
begin
    if (reset)
        pout <= 1'b0;
    else if (sclk_en) begin
        if (push & ~pop & data_vld)
            pout <= pout + 1'b1;
        else if (~push && pop && pout != 1'b0)
            pout <= pout - 1'b1;
    end
end

integer i;
always @(posedge sclk)
begin
    if (sclk_en) begin
        if (push) begin
            for (i = 0; i < DEPTH - 1; i = i + 1) begin
                mem[i+1] <= mem[i];
            end
            mem[0] <= data;
        end
    end
end
endmodule

Code is generated from Xilinx Vivado HLS

 

full_n : FIFO queue is not full which means enqueuing is available

empty_n : FIFO queue is not empty which means output q is valid

 

'Programming > Verilog' 카테고리의 다른 글

AXI Buffer  (1) 2020.04.04
Verilog log2 function  (0) 2020.02.13
AXI Register Slice  (0) 2020.02.12
Verilog Generate  (2) 2018.07.05
Xilinx bootgen  (0) 2017.06.21
module example_a_m_axi_reg_slice
#(parameter
    N = 8   // data width
) (
    // system signals
    input  wire         sclk,
    input  wire         reset,
    // slave side
    input  wire [N-1:0] s_data,
    input  wire         s_valid,
    output wire         s_ready,
    // master side
    output wire [N-1:0] m_data,
    output wire         m_valid,
    input  wire         m_ready
);
//------------------------Parameter----------------------
// state
localparam [1:0]
    ZERO = 2'b10,
    ONE  = 2'b11,
    TWO  = 2'b01;
//------------------------Local signal-------------------
reg  [N-1:0] data_p1;
reg  [N-1:0] data_p2;
wire         load_p1;
wire         load_p2;
wire         load_p1_from_p2;
reg          s_ready_t;
reg  [1:0]   state;
reg  [1:0]   next;
//------------------------Body---------------------------
assign s_ready = s_ready_t;
assign m_data  = data_p1;
assign m_valid = state[0];

assign load_p1 = (state == ZERO && s_valid) ||
                 (state == ONE && s_valid && m_ready) ||
                 (state == TWO && m_ready);
assign load_p2 = s_valid & s_ready;
assign load_p1_from_p2 = (state == TWO);

// data_p1
always @(posedge sclk) begin
    if (load_p1) begin
        if (load_p1_from_p2)
            data_p1 <= data_p2;
        else
            data_p1 <= s_data;
    end
end

// data_p2
always @(posedge sclk) begin
    if (load_p2) data_p2 <= s_data;
end

// s_ready_t
always @(posedge sclk) begin
    if (reset)
        s_ready_t <= 1'b0;
    else if (state == ZERO)
        s_ready_t <= 1'b1;
    else if (state == ONE && next == TWO)
        s_ready_t <= 1'b0;
    else if (state == TWO && next == ONE)
        s_ready_t <= 1'b1;
end

// state
always @(posedge sclk) begin
    if (reset)
        state <= ZERO;
    else
        state <= next;
end

// next
always @(*) begin
    case (state)
        ZERO:
            if (s_valid & s_ready)
                next = ONE;
            else
                next = ZERO;
        ONE:
            if (~s_valid & m_ready)
                next = ZERO;
            else if (s_valid & ~m_ready)
                next = TWO;
            else
                next = ONE;
        TWO:
            if (m_ready)
                next = ONE;
            else
                next = TWO;
        default:
            next = ZERO;
    endcase
end

endmodule

code is generated from Xilinx Vivado HLS

 

 AXI Interface 연결 간(Interconnect 등)에 동작 Clock frequency 증가를 위한 대표적인 Logic으로 Channel 간 Handshake 사이의 일종의 Pipeline register로 동작함

'Programming > Verilog' 카테고리의 다른 글

Verilog log2 function  (0) 2020.02.13
AXI FIFO  (0) 2020.02.13
Verilog Generate  (2) 2018.07.05
Xilinx bootgen  (0) 2017.06.21
Xilinx SDK disable cache  (0) 2017.06.12

+ Recent posts