module example_a_m_axi_buffer
#(parameter
    MEM_STYLE  = "block",
    DATA_WIDTH = 32,
    ADDR_WIDTH = 5,
    DEPTH      = 32
) (
    // system signal
    input  wire                  clk,
    input  wire                  reset,
    input  wire                  sclk_en,

    // write
    output wire                  if_full_n,
    input  wire                  if_write_ce,
    input  wire                  if_write,
    input  wire [DATA_WIDTH-1:0] if_din,

    // read
    output wire                  if_empty_n,
    input  wire                  if_read_ce,
    input  wire                  if_read,
    output wire [DATA_WIDTH-1:0] if_dout
);
//------------------------Parameter----------------------

//------------------------Local signal-------------------
(* ram_style = MEM_STYLE *)
reg  [DATA_WIDTH-1:0] mem[0:DEPTH-1];
reg  [DATA_WIDTH-1:0] q_buf = 1'b0;
reg  [ADDR_WIDTH-1:0] waddr = 1'b0;
reg  [ADDR_WIDTH-1:0] raddr = 1'b0;
wire [ADDR_WIDTH-1:0] wnext;
wire [ADDR_WIDTH-1:0] rnext;
wire                  push;
wire                  pop;
reg  [ADDR_WIDTH-1:0] usedw = 1'b0;
reg                   full_n = 1'b1;
reg                   empty_n = 1'b0;
reg  [DATA_WIDTH-1:0] q_tmp = 1'b0;
reg                   show_ahead = 1'b0;
reg  [DATA_WIDTH-1:0] dout_buf = 1'b0;
reg                   dout_valid = 1'b0;


//------------------------Instantiation------------------

//------------------------Task and function--------------

//------------------------Body---------------------------
assign if_full_n  = full_n;
assign if_empty_n = dout_valid;
assign if_dout    = dout_buf;
assign push       = full_n & if_write_ce & if_write;
assign pop        = empty_n & if_read_ce & (~dout_valid | if_read);
assign wnext      = !push                ? waddr :
                    (waddr == DEPTH - 1) ? 1'b0  :
                    waddr + 1'b1;
assign rnext      = !pop                 ? raddr :
                    (raddr == DEPTH - 1) ? 1'b0  :
                    raddr + 1'b1;

// waddr
always @(posedge clk) begin
    if (reset == 1'b1)
        waddr <= 1'b0;
    else if (sclk_en)
        waddr <= wnext;
end

// raddr
always @(posedge clk) begin
    if (reset == 1'b1)
        raddr <= 1'b0;
    else if (sclk_en)
        raddr <= rnext;
end

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

// full_n
always @(posedge clk) begin
    if (reset == 1'b1)
        full_n <= 1'b1;
    else if (sclk_en)
        if (push & ~pop)
            full_n <= (usedw != DEPTH - 1);
        else if (~push & pop)
            full_n <= 1'b1;
end

// empty_n
always @(posedge clk) begin
    if (reset == 1'b1)
        empty_n <= 1'b0;
    else if (sclk_en)
        if (push & ~pop)
            empty_n <= 1'b1;
        else if (~push & pop)
            empty_n <= (usedw != 1'b1);
end

// mem
always @(posedge clk) begin
    if (push)
        mem[waddr] <= if_din;
end

// q_buf
always @(posedge clk) begin
    q_buf <= mem[rnext];
end

// q_tmp
always @(posedge clk) begin
    if (reset == 1'b1)
        q_tmp <= 1'b0;
    else if (sclk_en)
        if (push)
            q_tmp <= if_din;
end

// show_ahead
always @(posedge clk) begin
    if (reset == 1'b1)
        show_ahead <= 1'b0;
    else if (sclk_en)
        if (push && usedw == pop)
            show_ahead <= 1'b1;
        else
            show_ahead <= 1'b0;
end

// dout_buf
always @(posedge clk) begin
    if (reset == 1'b1)
        dout_buf <= 1'b0;
    else if (sclk_en)
        if (pop)
            dout_buf <= show_ahead? q_tmp : q_buf;
end

// dout_valid
always @(posedge clk) begin
    if (reset == 1'b1)
        dout_valid <= 1'b0;
    else if (sclk_en)
        if (pop)
            dout_valid <= 1'b1;
        else if (if_read_ce & if_read)
            dout_valid <= 1'b0;
end

endmodule

code is generated from Xilinx Vivado HLS

 

full_n : queue is not full which means enqueuing is available

empty_n : queue is not empty which means pop is available

 

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

Verilog log2 function  (0) 2020.02.13
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
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

Verilog에서 보다 깔끔하면서 configurable 한 코드를 만들기 위해 generate 문을 활용할 수 있다.

일반적으로 자주 사용하는 문법은 아니지만, 긴 코드를 작성할 때 유리하다.


generate 문은 일반적인 verilog 문법과는 다르게, pre-compile 된다고 이해하면 쉽다.

(C언어에서의 전처리기 명령어(#define 등)와 비슷하다.)


generate 문에는 아래와 같이 2가지 종류가 있다.

1. generate loop

일반적으로 verilog에서는 for 문을 사용하지 않는다. Verilog에서 사용하는 for 문은 사실 generate 문의 일부이다.

loop index는 genvar로 선언하여야 하며, generate loop 내에서 선언된 wire 등은 loop iteration 간의 충돌이 일어나지 않는다.(local 변수로 이해하면 된다.)

genvar idx;

generate

for(idx = 0; idx < 3; idx = idx + 1) begin : gen_inst

wire w1, w2;

assign w1 = in1[idx] & in2[idx];

assign w2 = in1[idx] | in2[idx];

assign out[idx] = w1 & w2;

end

endgenerate

위의 코드는 아래와 같다.

wire gen_inst[0].w1, gen_inst[0].w2;

assign gen_inst[0].w1 = in1[0] & in2[0];

assign gen_inst[0].w2 = in1[0] | in2[0];

assign out[0] = gen_inst[0].w1 & gen_inst[0].w2;

wire gen_inst[1].w1, gen_inst[1].w2;

assign gen_inst[1].w1 = in1[1] & in2[1];

assign gen_inst[1].w2 = in1[1] | in2[1];

assign out[1] = gen_inst[1].w1 & gen_inst[1].w2;

wire gen_inst[2].w1, gen_inst[2].w2;

assign gen_inst[2].w1 = in1[2] & in2[2];

assign gen_inst[2].w2 = in1[2] | in2[2];

assign out[2] = gen_inst[2].w1 & gen_inst[2].w2;

2. if-generate / case-generate

if-generate와 case-generate는 코드에는 등장하지만, 조건에 따라서 실제 synthesis 되지 않는 코드를 말한다.

간단히 이해하기로는, parameter 등 constant 한 값에 의한 if / case 문에서 해당될 수 없는 구문은 애초에 없는 코드로 생각하면 된다.


주의 사항

 - generate 문은 generate 와 endgenerate 사이로 구성할 수 있으나 사실 이는 필수는 아니다.

 - generate 문은 named / unamed 둘 다 가능하나, named로 사용하는 편이 좋다.


참조: http://www.verilogpro.com/verilog-generate-configurable-rtl/

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

AXI FIFO  (0) 2020.02.13
AXI Register Slice  (0) 2020.02.12
Xilinx bootgen  (0) 2017.06.21
Xilinx SDK disable cache  (0) 2017.06.12
Xilinx Vivado IP import  (0) 2017.05.31

Xilinx bootgen 을 이용해 boot.bin 파일을 생성하면,

boot.bif 에 담긴 파일들(FSBL, bitstream, u-boot)이 boot.bin 으로 합쳐진다.


따라서, 해당 파일들을 boot partition에 넣을 필요 없이,

boot.bin 만 넣어주면 문제 없이 작동한다.

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

AXI Register Slice  (0) 2020.02.12
Verilog Generate  (2) 2018.07.05
Xilinx SDK disable cache  (0) 2017.06.12
Xilinx Vivado IP import  (0) 2017.05.31
Xilinx Vivado Project가 안 열릴때  (0) 2017.05.30

Xilinx SDK 에서 Baremetal로 실험할 때,

Icache / Dcache를 disable 할 수 있다.


hello world 프로젝트를 생성하면, 기본적으로 platform 헤더를 include 하면서, init_platform() 으로 시작 / cleanup_platform() 으로 끝을 내는 함수를 준다.

여기서 init_platform() 함수에서 Icache, Dcache 모두를 enable 시키는 데, 이를 지움으로써, Cache를 disable 시킬 수 있다.

다만, Cache를 disable 한다는 것은 Cache에 write를 하지 않는 다는 것을 의미해, 기존에 cache 에 있던 data는 cache로 부터 읽어짐을 기억하자!

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

AXI Register Slice  (0) 2020.02.12
Verilog Generate  (2) 2018.07.05
Xilinx bootgen  (0) 2017.06.21
Xilinx Vivado IP import  (0) 2017.05.31
Xilinx Vivado Project가 안 열릴때  (0) 2017.05.30

Xilinx Vivado 에서 3rd party 혹은 customized IP 를 Import 하고자 하는 경우



Tools - Project Settings


Add IP Repositories in IP tab



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

AXI Register Slice  (0) 2020.02.12
Verilog Generate  (2) 2018.07.05
Xilinx bootgen  (0) 2017.06.21
Xilinx SDK disable cache  (0) 2017.06.12
Xilinx Vivado Project가 안 열릴때  (0) 2017.05.30

Error when launching "Vivado"

Launcher time out


위와 같은 Error로 Xilinx vivado가 열리지 않는 경우,

project path에 들어가면 안되는 문자가 들어가 있는 경우 일 수 있다.


path에 포함되면 Error를 일으키는 문자: 괄호( )



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

AXI Register Slice  (0) 2020.02.12
Verilog Generate  (2) 2018.07.05
Xilinx bootgen  (0) 2017.06.21
Xilinx SDK disable cache  (0) 2017.06.12
Xilinx Vivado IP import  (0) 2017.05.31

+ Recent posts