129 lines
2.2 KiB
Verilog
129 lines
2.2 KiB
Verilog
`timescale 1ns / 1ps
|
|
|
|
`include "src/fifo.v"
|
|
`include "src/rmii/rmii_serializer.v"
|
|
|
|
module rmii_transmit_controller #(
|
|
parameter FIFO_DEPTH = 16,
|
|
parameter STORAGE_WIDTH = 8,
|
|
|
|
// AUTOCALCULATED
|
|
parameter STORAGE_MSB = STORAGE_WIDTH - 1,
|
|
parameter SHIFT_COUNT = FIFO_DEPTH
|
|
)(
|
|
input clk, rst, clear, // general signals
|
|
|
|
/* FIFO signals */
|
|
input [STORAGE_MSB:0] data_in, // input data
|
|
input wrt, // store the data
|
|
output not_full, // the internal buffer is not full
|
|
|
|
/* RMII signals */
|
|
output reg TXEN, // transmit enable
|
|
output [1:0] TXD, // transmit data
|
|
|
|
output reg busy // there's an ongoing transmission
|
|
);
|
|
|
|
wire rstclr = rst | clear;
|
|
|
|
/* TX FIFO and its signals */
|
|
wire tx_fifo_empty;
|
|
wire tx_fifo_out_valid;
|
|
wire tx_fifo_full;
|
|
wire [STORAGE_WIDTH-1:0]tx_fifo_out;
|
|
//wire start = wrt && !busy;
|
|
wire tx_fifo_pop = (busy && oser_empty) || oser_single;
|
|
|
|
fifo #(
|
|
.DEPTH(FIFO_DEPTH),
|
|
.WIDTH(STORAGE_WIDTH)
|
|
) tx_fifo (
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.clear(clear),
|
|
|
|
.empty(tx_fifo_empty),
|
|
.out_valid(tx_fifo_out_valid),
|
|
.full(tx_fifo_full),
|
|
|
|
.in(data_in),
|
|
.push(wrt),
|
|
|
|
.out(tx_fifo_out),
|
|
.pop(tx_fifo_pop)
|
|
);
|
|
|
|
assign not_full = !tx_fifo_full;
|
|
|
|
/* output serializer */
|
|
|
|
wire oser_load = tx_fifo_out_valid;
|
|
wire oser_empty;
|
|
//wire oser_exhausted;
|
|
wire oser_single;
|
|
wire [1:0] oser_out;
|
|
|
|
rmii_serializer #(
|
|
.STORE_SIZE(STORAGE_WIDTH),
|
|
.DIR(1) // RIGHT
|
|
) out_serializer (
|
|
.clk(clk),
|
|
.rst(rst),
|
|
.clear(clear),
|
|
|
|
.par_in(tx_fifo_out),
|
|
.ser_out(oser_out),
|
|
.load(oser_load),
|
|
.shift(1'b1),
|
|
.single(oser_single),
|
|
.empty(oser_empty),
|
|
.exhausted(/*oser_exhausted*/)
|
|
);
|
|
|
|
/* TXEN control */
|
|
always @(posedge clk)
|
|
begin
|
|
if (rstclr)
|
|
begin
|
|
TXEN <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (oser_load) // assert the same time the shift register loading occurs
|
|
begin
|
|
TXEN <= 1;
|
|
end
|
|
else if (oser_empty && tx_fifo_empty) // deassert only when all buffers has depleted
|
|
begin
|
|
TXEN <= 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
/* busy control */
|
|
always @(posedge clk)
|
|
begin
|
|
if (rstclr)
|
|
begin
|
|
busy <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (!busy && wrt)
|
|
begin
|
|
busy <= 1;
|
|
end
|
|
|
|
if (busy && !wrt && !TXEN)
|
|
begin
|
|
busy <= 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
// combinatorial output
|
|
assign TXD = TXEN ? oser_out : 2'b0;
|
|
|
|
endmodule
|