177 lines
4.9 KiB
Verilog
177 lines
4.9 KiB
Verilog
|
|
//
|
|
// Copyright 2013 Ettus Research LLC
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
//create a compressed vita based uart data interface
|
|
|
|
module cvita_uart
|
|
#(
|
|
parameter SIZE = 0
|
|
)
|
|
(
|
|
//clocking interface
|
|
input clk, input rst,
|
|
|
|
//uart interface
|
|
input rxd, output txd,
|
|
|
|
//chdr fifo input
|
|
input [63:0] i_tdata,
|
|
input i_tlast,
|
|
input i_tvalid,
|
|
output i_tready,
|
|
|
|
//chdr fifo output
|
|
output [63:0] o_tdata,
|
|
output o_tlast,
|
|
output o_tvalid,
|
|
input o_tready
|
|
);
|
|
|
|
reg [31:0] sid;
|
|
|
|
//baud clock divider
|
|
reg [15:0] clkdiv;
|
|
|
|
//hold rx in disable until a tx event
|
|
reg rxd_enable;
|
|
|
|
//==================================================================
|
|
//== RXD capture and packet generation interface
|
|
//==================================================================
|
|
wire [7:0] rx_char;
|
|
wire fifo_empty;
|
|
wire fifo_read;
|
|
reg [11:0] seqnum;
|
|
wire pgen_trigger;
|
|
wire pgen_done;
|
|
|
|
//rx uart capture
|
|
simple_uart_rx #(.SIZE(SIZE)) simple_uart_rx
|
|
(
|
|
.clk(clk), .rst(rst),
|
|
.fifo_out(rx_char), .fifo_read(fifo_read), .fifo_level(), .fifo_empty(fifo_empty),
|
|
.clkdiv(clkdiv), .rx(rxd)
|
|
);
|
|
|
|
//packet generation - holds rx character
|
|
context_packet_gen context_packet_gen
|
|
(
|
|
.clk(clk), .reset(rst), .clear(1'b0),
|
|
.trigger(pgen_trigger),
|
|
.seqnum(seqnum),
|
|
.sid({sid[15:0], sid[31:16]}),
|
|
.body({56'b0, rx_char}),
|
|
.vita_time(64'b0),
|
|
|
|
.done(pgen_done),
|
|
.o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready)
|
|
);
|
|
|
|
//state machine to manage pgen and rx uart
|
|
reg [1:0] rxd_state;
|
|
localparam RXD_STATE_RECV_CHAR = 0;
|
|
localparam RXD_STATE_PGEN_TRIG = 1;
|
|
localparam RXD_STATE_WAIT_DONE = 2;
|
|
localparam RXD_STATE_READ_FIFO = 3;
|
|
|
|
always @(posedge clk) begin
|
|
if (rst) begin
|
|
seqnum <= 12'b0;
|
|
rxd_state <= RXD_STATE_RECV_CHAR;
|
|
end
|
|
else case (rxd_state)
|
|
|
|
RXD_STATE_RECV_CHAR: begin
|
|
if (!fifo_empty && rxd_enable) rxd_state <= RXD_STATE_PGEN_TRIG;
|
|
end
|
|
|
|
RXD_STATE_PGEN_TRIG: begin
|
|
rxd_state <= RXD_STATE_WAIT_DONE;
|
|
end
|
|
|
|
RXD_STATE_WAIT_DONE: begin
|
|
if (pgen_done) rxd_state <= RXD_STATE_READ_FIFO;
|
|
end
|
|
|
|
RXD_STATE_READ_FIFO: begin
|
|
rxd_state <= RXD_STATE_RECV_CHAR;
|
|
seqnum <= seqnum + 1'b1;
|
|
end
|
|
|
|
endcase //rxd_state
|
|
end
|
|
|
|
assign fifo_read = (rxd_state == RXD_STATE_READ_FIFO) || (!rxd_enable);
|
|
assign pgen_trigger = (rxd_state == RXD_STATE_PGEN_TRIG);
|
|
|
|
//==================================================================
|
|
//== TXD generation and packet control interface
|
|
//==================================================================
|
|
wire [7:0] tx_char;
|
|
wire fifo_write;
|
|
wire fifo_full;
|
|
|
|
simple_uart_tx #(.SIZE(SIZE)) simple_uart_tx
|
|
(
|
|
.clk(clk), .rst(rst),
|
|
.fifo_in(tx_char), .fifo_write(fifo_write), .fifo_level(), .fifo_full(fifo_full),
|
|
.clkdiv(clkdiv), .baudclk(), .tx(txd)
|
|
);
|
|
|
|
//state machine to manage control and tx uart
|
|
reg [1:0] txd_state;
|
|
localparam TXD_STATE_RECV_CHDR = 0;
|
|
localparam TXD_STATE_RECV_TIME = 1;
|
|
localparam TXD_STATE_RECV_BODY = 2;
|
|
localparam TXD_STATE_DROP_FIFO = 3;
|
|
|
|
always @(posedge clk) begin
|
|
if (rst) begin;
|
|
txd_state <= TXD_STATE_RECV_CHDR;
|
|
rxd_enable <= 1'b0;
|
|
end
|
|
if (i_tvalid && i_tready) case (txd_state)
|
|
|
|
TXD_STATE_RECV_CHDR: begin
|
|
txd_state <= (i_tdata[61])? TXD_STATE_RECV_TIME : TXD_STATE_RECV_BODY;
|
|
sid <= i_tdata[31:0];
|
|
end
|
|
|
|
TXD_STATE_RECV_TIME: begin
|
|
txd_state <= TXD_STATE_RECV_BODY;
|
|
end
|
|
|
|
TXD_STATE_RECV_BODY: begin
|
|
txd_state <= (i_tlast)? TXD_STATE_RECV_CHDR : TXD_STATE_DROP_FIFO;
|
|
clkdiv <= i_tdata[47:32];
|
|
rxd_enable <= 1'b1;
|
|
end
|
|
|
|
TXD_STATE_DROP_FIFO: begin
|
|
if (i_tlast) txd_state <= TXD_STATE_RECV_CHDR;
|
|
end
|
|
|
|
endcase //txd_state
|
|
end
|
|
|
|
assign tx_char = i_tdata[7:0];
|
|
assign fifo_write = (txd_state == TXD_STATE_RECV_BODY) && i_tvalid && i_tready;
|
|
assign i_tready = !fifo_full;
|
|
|
|
endmodule // cvita_uart
|