1 2// 3// Copyright 2013 Ettus Research LLC 4// Copyright 2018 Ettus Research, a National Instruments Company 5// 6// SPDX-License-Identifier: LGPL-3.0-or-later 7// 8 9 10//create a compressed vita based uart data interface 11 12module cvita_uart 13#( 14 parameter SIZE = 0 15) 16( 17 //clocking interface 18 input clk, input rst, 19 20 //uart interface 21 input rxd, output txd, 22 23 //chdr fifo input 24 input [63:0] i_tdata, 25 input i_tlast, 26 input i_tvalid, 27 output i_tready, 28 29 //chdr fifo output 30 output [63:0] o_tdata, 31 output o_tlast, 32 output o_tvalid, 33 input o_tready 34); 35 36 reg [31:0] sid; 37 38 //baud clock divider 39 reg [15:0] clkdiv; 40 41 //hold rx in disable until a tx event 42 reg rxd_enable; 43 44 //================================================================== 45 //== RXD capture and packet generation interface 46 //================================================================== 47 wire [7:0] rx_char; 48 wire fifo_empty; 49 wire fifo_read; 50 reg [11:0] seqnum; 51 wire pgen_trigger; 52 wire pgen_done; 53 54 //rx uart capture 55 simple_uart_rx #(.SIZE(SIZE)) simple_uart_rx 56 ( 57 .clk(clk), .rst(rst | ~rxd_enable), 58 .fifo_out(rx_char), .fifo_read(fifo_read), .fifo_level(), .fifo_empty(fifo_empty), 59 .clkdiv(clkdiv), .rx(rxd) 60 ); 61 62 //packet generation - holds rx character 63 context_packet_gen context_packet_gen 64 ( 65 .clk(clk), .reset(rst), .clear(1'b0), 66 .trigger(pgen_trigger), 67 .seqnum(seqnum), 68 .sid({sid[15:0], sid[31:16]}), 69 .body({56'b0, rx_char}), 70 .vita_time(64'b0), 71 72 .done(pgen_done), 73 .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready) 74 ); 75 76 //state machine to manage pgen and rx uart 77 reg [1:0] rxd_state; 78 localparam RXD_STATE_RECV_CHAR = 0; 79 localparam RXD_STATE_PGEN_TRIG = 1; 80 localparam RXD_STATE_WAIT_DONE = 2; 81 localparam RXD_STATE_READ_FIFO = 3; 82 83 always @(posedge clk) begin 84 if (rst) begin 85 seqnum <= 12'b0; 86 rxd_state <= RXD_STATE_RECV_CHAR; 87 end 88 else case (rxd_state) 89 90 RXD_STATE_RECV_CHAR: begin 91 if (!fifo_empty && rxd_enable) rxd_state <= RXD_STATE_PGEN_TRIG; 92 end 93 94 RXD_STATE_PGEN_TRIG: begin 95 rxd_state <= RXD_STATE_WAIT_DONE; 96 end 97 98 RXD_STATE_WAIT_DONE: begin 99 if (pgen_done) rxd_state <= RXD_STATE_READ_FIFO; 100 end 101 102 RXD_STATE_READ_FIFO: begin 103 rxd_state <= RXD_STATE_RECV_CHAR; 104 seqnum <= seqnum + 1'b1; 105 end 106 107 endcase //rxd_state 108 end 109 110 assign fifo_read = (rxd_state == RXD_STATE_READ_FIFO) || (!rxd_enable); 111 assign pgen_trigger = (rxd_state == RXD_STATE_PGEN_TRIG); 112 113 //================================================================== 114 //== TXD generation and packet control interface 115 //================================================================== 116 wire [7:0] tx_char; 117 wire fifo_write; 118 wire fifo_full; 119 120 simple_uart_tx #(.SIZE(SIZE)) simple_uart_tx 121 ( 122 .clk(clk), .rst(rst), 123 .fifo_in(tx_char), .fifo_write(fifo_write), .fifo_level(), .fifo_full(fifo_full), 124 .clkdiv(clkdiv), .baudclk(), .tx(txd) 125 ); 126 127 //state machine to manage control and tx uart 128 reg [1:0] txd_state; 129 localparam TXD_STATE_RECV_CHDR = 0; 130 localparam TXD_STATE_RECV_TIME = 1; 131 localparam TXD_STATE_RECV_BODY = 2; 132 localparam TXD_STATE_DROP_FIFO = 3; 133 134 always @(posedge clk) begin 135 if (rst) begin; 136 txd_state <= TXD_STATE_RECV_CHDR; 137 rxd_enable <= 1'b0; 138 end 139 if (i_tvalid && i_tready) case (txd_state) 140 141 TXD_STATE_RECV_CHDR: begin 142 txd_state <= (i_tdata[61])? TXD_STATE_RECV_TIME : TXD_STATE_RECV_BODY; 143 sid <= i_tdata[31:0]; 144 end 145 146 TXD_STATE_RECV_TIME: begin 147 txd_state <= TXD_STATE_RECV_BODY; 148 end 149 150 TXD_STATE_RECV_BODY: begin 151 txd_state <= (i_tlast)? TXD_STATE_RECV_CHDR : TXD_STATE_DROP_FIFO; 152 clkdiv <= i_tdata[47:32]; 153 rxd_enable <= 1'b1; 154 end 155 156 TXD_STATE_DROP_FIFO: begin 157 if (i_tlast) txd_state <= TXD_STATE_RECV_CHDR; 158 end 159 160 endcase //txd_state 161 end 162 163 assign tx_char = i_tdata[7:0]; 164 assign fifo_write = (txd_state == TXD_STATE_RECV_BODY) && i_tvalid && i_tready; 165 assign i_tready = !fifo_full; 166 167endmodule // cvita_uart 168