Skip to content

Commit

Permalink
feat(nco, axis): fix NCO, AXIS IN, AXIS OUT
Browse files Browse the repository at this point in the history
- update iob_nco module with new clock in domain, fix CDC problems
    - NOTE: linux software is outdated
- add iob_axistream in and out modules, fix CDC problems
    - NOTE: axistream in still needs better CDC for `axis_word_count` to
      `NWORDS_rd`. Maybe use gray counter
  • Loading branch information
P-Miranda committed Oct 30, 2024
1 parent 74e6da9 commit d4c2b40
Show file tree
Hide file tree
Showing 26 changed files with 2,332 additions and 57 deletions.
2 changes: 2 additions & 0 deletions submodules/LIB/hardware/modules/fifo2axis/fifo2axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from iob_module import iob_module
from iob_reg_re import iob_reg_re
from iob_modcnt import iob_modcnt


class fifo2axis(iob_module):
Expand All @@ -15,6 +16,7 @@ def _create_submodules_list(cls):
super()._create_submodules_list(
[
iob_reg_re,
iob_modcnt,
{"interface": "clk_en_rst_s_port"},
{"interface": "clk_en_rst_s_s_portmap"},
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,30 @@ module fifo2axis #(

//FIFO tlast
wire axis_tlast_nxt;
assign axis_tlast_nxt = (axis_word_count == len_i);
wire [AXIS_LEN_W-1:0] len_int;

assign len_int = len_i - 1'b1;
assign axis_tlast_nxt = (axis_word_count == len_int);
iob_reg_re #(
.DATA_W (1),
.RST_VAL(1'd0)
) axis_tlast_reg (
`include "clk_en_rst_s_s_portmap.vs"
.rst_i (rst_i),
.en_i (en_i),
.en_i (pipe_en),
.data_i(axis_tlast_nxt),
.data_o(axis_tlast_o)
);

//tdata word count
iob_counter #(
iob_modcnt #(
.DATA_W (AXIS_LEN_W),
.RST_VAL(0)
.RST_VAL({AXIS_LEN_W{1'b1}}) // go to 0 after first enable
) word_count_inst (
`include "clk_en_rst_s_s_portmap.vs"
.rst_i (rst_i),
.en_i (fifo_read_o),
.mod_i (len_int),
.data_o(axis_word_count)
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
`timescale 1ns / 1ps
`include "iob_utils.vh"
`include "iob_axistream_in_conf.vh"
`include "iob_axistream_in_swreg_def.vh"

module iob_axistream_in #(
`include "iob_axistream_in_params.vs"
) (
`include "iob_axistream_in_io.vs"
);

localparam R = DATA_W / TDATA_W;
localparam R_W = $clog2(R);
localparam RAM_ADDR_W = FIFO_ADDR_W - $clog2(R);

//rst and enable synced to axis_clk
wire axis_sw_rst;
wire axis_sw_enable;
wire axis_sw_mode;

//fifo write
wire axis_fifo_write;
wire axis_fifo_full;

//tlast detected
wire axis_tlast;
wire axis_tlast_detected;

//word counter
wire [ DATA_W-1:0] axis_word_count;
wire axis_word_count_en;


//fifo read
wire fifo_read;
wire [ DATA_W-1:0] fifo_data;
wire fifo_empty;
wire [((FIFO_ADDR_W+1 > 1) ? FIFO_ADDR_W+1 : 1)-1:0] fifo_level;

//fifo RAM
wire ext_mem_w_clk;
wire [ R-1:0] ext_mem_w_en;
wire [RAM_ADDR_W-1:0] ext_mem_w_addr;
wire [ DATA_W-1:0] ext_mem_w_data;
wire ext_mem_r_clk;
wire [ R-1:0] ext_mem_r_en;
wire [RAM_ADDR_W-1:0] ext_mem_r_addr;
wire [ DATA_W-1:0] ext_mem_r_data;

wire int_tvalid;
wire [DATA_W-1:0] int_tdata;
wire int_tready;

// configuration control and status register file.
`include "iob_axistream_in_swreg_inst.vs"

wire tlast_detected_reg;

//CPU INTERFACE
assign DATA_rready_rd = int_tvalid;
assign interrupt_o = FIFO_LEVEL_rd >= FIFO_THRESHOLD_wr;
assign DATA_rvalid_rd = int_tvalid & (~MODE_wr);
assign DATA_rdata_rd = int_tdata;

//System Stream output interface
// System output valid only if in system stream mode
assign sys_tvalid_o = int_tvalid & MODE_wr;
assign sys_tdata_o = int_tdata;

assign int_tready = (MODE_wr) ? sys_tready_i : DATA_ren_rd;

// empty = fifo empty + no data in fifo2axis
assign FIFO_EMPTY_rd = fifo_empty & (~int_tvalid);
// level = fifo level + data in fifo2axis
assign FIFO_LEVEL_rd = fifo_level + int_tvalid;

wire ready_int;
// Ready if not full and, if in CSR mode, tlast not detected
assign ready_int = ~axis_fifo_full & axis_sw_enable & ~(~axis_sw_mode & tlast_detected_reg);

//word count enable
assign axis_word_count_en = axis_fifo_write & ~tlast_detected_reg;

generate
if (R == 1) begin : gen_no_padding
//AXI Stream input interface
assign axis_tready_o = ready_int;
//FIFO write
assign axis_fifo_write = axis_tvalid_i & axis_tready_o;
end else begin : gen_padding
//FIFO write FSM
reg fifo_write_state_nxt;
wire fifo_write_state;
always @* begin
fifo_write_state_nxt = fifo_write_state;
case (fifo_write_state)
0: begin // Idle
// If tvalid, fifo not full, tlast, and the write wont fill the DATA_W with TDATA_W
if (((axis_tvalid_i & ~axis_fifo_full) & axis_tlast_i) &
axis_word_count[0+:R_W] != {R_W{1'd1}}) begin
fifo_write_state_nxt = 1'b1;
end
end
default: begin // Padding
if (axis_word_count[0+:R_W] == {R_W{1'd1}} && ~axis_fifo_full) begin
fifo_write_state_nxt = 1'b0;
end
end
endcase
end

iob_reg_re #(
.DATA_W (1),
.RST_VAL(1'd0)
) fifo_write_state_reg (
.clk_i (axis_clk_i),
.cke_i (axis_cke_i),
.arst_i(axis_arst_i),
.rst_i (axis_sw_rst),
.en_i (axis_sw_enable),
.data_i(fifo_write_state_nxt),
.data_o(fifo_write_state)
);

// Ready if not full, if in CSR mode, tlast not detected and not in padding state
assign axis_tready_o = ready_int & ~fifo_write_state;
//FIFO write if tvalid, tlast, not full or in padding state
assign axis_fifo_write = (axis_tvalid_i & axis_tready_o) | fifo_write_state;
end
endgenerate

//tlast
assign axis_tlast = axis_tlast_i & axis_fifo_write;

// received words counter
iob_counter #(
.DATA_W (DATA_W),
.RST_VAL(0)
) word_count_inst (
.clk_i (axis_clk_i),
.cke_i (axis_cke_i),
.arst_i(axis_arst_i),
.rst_i (axis_sw_rst),
.en_i (axis_word_count_en),
.data_o(axis_word_count)
);


//Synchronizers from clk (swregs) to axis domain
iob_sync #(
.DATA_W (1),
.RST_VAL(1'd0)
) sw_rst (
.clk_i (axis_clk_i),
.arst_i (axis_arst_i),
.signal_i(SOFT_RESET_wr),
.signal_o(axis_sw_rst)
);

iob_sync #(
.DATA_W (1),
.RST_VAL(1'd0)
) sw_enable (
.clk_i (axis_clk_i),
.arst_i (axis_arst_i),
.signal_i(ENABLE_wr),
.signal_o(axis_sw_enable)
);

iob_sync #(
.DATA_W (1),
.RST_VAL(1'd0)
) sw_mode (
.clk_i (axis_clk_i),
.arst_i (axis_arst_i),
.signal_i(MODE_wr),
.signal_o(axis_sw_mode)
);


//Synchronizers from axis to clk domain (sw_regs)
iob_sync #(
.DATA_W (1),
.RST_VAL(1'd0)
) tlast_detected_sync (
.clk_i (clk_i),
.arst_i (arst_i),
.signal_i(tlast_detected_reg),
.signal_o(TLAST_DETECTED_rd)
);

iob_sync #(
.DATA_W (DATA_W),
.RST_VAL(0)
) word_counter_sync (
.clk_i (clk_i),
.arst_i (arst_i),
.signal_i(axis_word_count),
.signal_o(NWORDS_rd)
);

//tlast detection
iob_edge_detect #(
.EDGE_TYPE("rising"),
.OUT_TYPE ("step")
) tlast_detect (
.clk_i (axis_clk_i),
.cke_i (axis_cke_i),
.arst_i (axis_arst_i),
.rst_i (axis_sw_rst),
.bit_i (axis_tlast),
.detected_o(axis_tlast_detected)
);

iob_reg #(
.DATA_W (1),
.RST_VAL(1'd0)
) tlast_detect_reg (
.clk_i (axis_clk_i),
.cke_i (axis_cke_i),
.arst_i(axis_arst_i),
.data_i(axis_tlast_detected),
.data_o(tlast_detected_reg)
);

//FIFOs RAM
genvar p;
generate
for (p = 0; p < R; p = p + 1) begin : gen_fifo_ram
iob_ram_t2p #(
.DATA_W(TDATA_W),
.ADDR_W(RAM_ADDR_W)
) iob_ram_t2p (
.w_clk_i (ext_mem_w_clk),
.w_en_i (ext_mem_w_en[p]),
.w_addr_i(ext_mem_w_addr),
.w_data_i(ext_mem_w_data[p*TDATA_W+:TDATA_W]),

.r_clk_i (ext_mem_r_clk),
.r_en_i (ext_mem_r_en[p]),
.r_addr_i(ext_mem_r_addr),
.r_data_o(ext_mem_r_data[p*TDATA_W+:TDATA_W])
);
end
endgenerate

fifo2axis #(
.DATA_W(DATA_W),
.AXIS_LEN_W(1)
) fifo2axis_inst (
`include "clk_en_rst_s_s_portmap.vs"
.rst_i(SOFT_RESET_wr),
.en_i(1'b1),
.len_i(1'b1),
// FIFO I/F
.fifo_empty_i(fifo_empty),
.fifo_read_o(fifo_read),
.fifo_rdata_i(fifo_data),
// AXIS I/F
.axis_tvalid_o(int_tvalid),
.axis_tdata_o(int_tdata),
.axis_tready_i(int_tready),
.axis_tlast_o()
);

//async fifo
iob_fifo_async #(
.W_DATA_W(TDATA_W),
.R_DATA_W(DATA_W),
.ADDR_W (FIFO_ADDR_W)
) data_fifo (
.ext_mem_w_clk_o (ext_mem_w_clk),
.ext_mem_w_en_o (ext_mem_w_en),
.ext_mem_w_addr_o(ext_mem_w_addr),
.ext_mem_w_data_o(ext_mem_w_data),
.ext_mem_r_clk_o (ext_mem_r_clk),
.ext_mem_r_en_o (ext_mem_r_en),
.ext_mem_r_addr_o(ext_mem_r_addr),
.ext_mem_r_data_i(ext_mem_r_data),
//read port (sys clk domain)
.r_clk_i (clk_i),
.r_cke_i (cke_i),
.r_arst_i (arst_i),
.r_rst_i (SOFT_RESET_wr),
.r_en_i (fifo_read),
.r_data_o (fifo_data),
.r_empty_o (fifo_empty),
.r_full_o (FIFO_FULL_rd),
.r_level_o (fifo_level),
//write port (axis clk domain)
.w_clk_i (axis_clk_i),
.w_cke_i (axis_cke_i),
.w_arst_i (axis_arst_i),
.w_rst_i (axis_sw_rst),
.w_en_i (axis_fifo_write),
.w_data_i (axis_tdata_i),
.w_empty_o (),
.w_full_o (axis_fifo_full),
.w_level_o ()
);

endmodule
Loading

0 comments on commit d4c2b40

Please sign in to comment.