📄 usbf_tx_phy.v
字号:
//// TX
module usbf_tx_phy(
clk, rst, fs_ce, phy_mode,
// Transciever Interface
txdp, txdn, txoe,
// UTMI Interface
DataOut_i, TxValid_i, TxReady_o
);
input clk;
input rst;
input fs_ce;
input phy_mode;
output txdp, txdn, txoe;
input [7:0] DataOut_i;
input TxValid_i;
output TxReady_o;
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
parameter IDLE = 3'd0,
SOP = 3'h1,
DATA = 3'h2,
EOP1 = 3'h3,
EOP2 = 3'h4,
WAIT = 3'h5;
reg TxReady_o;
reg [2:0] state, next_state;
reg tx_ready_d;
reg ld_sop_d;
reg ld_data_d;
reg ld_eop_d;
reg tx_ip;
reg tx_ip_sync;
reg [2:0] bit_cnt;
reg [7:0] hold_reg;
reg sd_raw_o;
wire hold;
reg data_done;
reg sft_done;
reg sft_done_r;
wire sft_done_e;
reg ld_data;
wire eop_done;
reg [2:0] one_cnt;
wire stuff;
reg sd_bs_o;
reg sd_nrzi_o;
reg append_eop;
reg append_eop_sync1;
reg append_eop_sync2;
reg append_eop_sync3;
reg txdp, txdn;
reg txoe_r1, txoe_r2;
reg txoe;
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) TxReady_o <= 1'b0;
else TxReady_o <= tx_ready_d & TxValid_i;
always @(posedge clk)
ld_data <= ld_data_d;
///////////////////////////////////////////////////////////////////
//
// Transmit in progress indicator
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) tx_ip <= 1'b0;
else
if(ld_sop_d) tx_ip <= 1'b1;
else
if(eop_done) tx_ip <= 1'b0;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) tx_ip_sync <= 1'b0;
else
if(fs_ce) tx_ip_sync <= tx_ip;
// data_done helps us to catch cases where TxValid drops due to
// packet end and then gets re-asserted as a new packet starts.
// We might not see this because we are still transmitting.
// data_done should solve those cases ...
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) data_done <= 1'b0;
else
if(TxValid_i && ! tx_ip) data_done <= 1'b1;
else
if(!TxValid_i) data_done <= 1'b0;
///////////////////////////////////////////////////////////////////
//
// Shift Register
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) bit_cnt <= 3'h0;
else
if(!tx_ip_sync) bit_cnt <= 3'h0;
else
if(fs_ce && !hold) bit_cnt <= bit_cnt + 3'h1;
assign hold = stuff;
always @(posedge clk)
if(!tx_ip_sync) sd_raw_o <= 1'b0;
else
case(bit_cnt) // synopsys full_case parallel_case
3'h0: sd_raw_o <= hold_reg[0];
3'h1: sd_raw_o <= hold_reg[1];
3'h2: sd_raw_o <= hold_reg[2];
3'h3: sd_raw_o <= hold_reg[3];
3'h4: sd_raw_o <= hold_reg[4];
3'h5: sd_raw_o <= hold_reg[5];
3'h6: sd_raw_o <= hold_reg[6];
3'h7: sd_raw_o <= hold_reg[7];
endcase
always @(posedge clk)
sft_done <= !hold & (bit_cnt == 3'h7);
always @(posedge clk)
sft_done_r <= sft_done;
assign sft_done_e = sft_done & !sft_done_r;
// Out Data Hold Register
always @(posedge clk)
if(ld_sop_d) hold_reg <= 8'h80;
else
if(ld_data) hold_reg <= DataOut_i;
///////////////////////////////////////////////////////////////////
//
// Bit Stuffer
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) one_cnt <= 3'h0;
else
if(!tx_ip_sync) one_cnt <= 3'h0;
else
if(fs_ce)
begin
if(!sd_raw_o || stuff) one_cnt <= 3'h0;
else one_cnt <= one_cnt + 3'h1;
end
assign stuff = (one_cnt==3'h6);
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) sd_bs_o <= 1'h0;
else
if(fs_ce) sd_bs_o <= !tx_ip_sync ? 1'b0 : (stuff ? 1'b0 : sd_raw_o);
///////////////////////////////////////////////////////////////////
//
// NRZI Encoder
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) sd_nrzi_o <= 1'b1;
else
if(!tx_ip_sync || !txoe_r1) sd_nrzi_o <= 1'b1;
else
if(fs_ce) sd_nrzi_o <= sd_bs_o ? sd_nrzi_o : ~sd_nrzi_o;
///////////////////////////////////////////////////////////////////
//
// EOP append logic
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop <= 1'b0;
else
if(ld_eop_d) append_eop <= 1'b1;
else
if(append_eop_sync2) append_eop <= 1'b0;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync1 <= 1'b0;
else
if(fs_ce) append_eop_sync1 <= append_eop;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync2 <= 1'b0;
else
if(fs_ce) append_eop_sync2 <= append_eop_sync1;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync3 <= 1'b0;
else
if(fs_ce) append_eop_sync3 <= append_eop_sync2;
assign eop_done = append_eop_sync3;
///////////////////////////////////////////////////////////////////
//
// Output Enable Logic
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txoe_r1 <= 1'b0;
else
if(fs_ce) txoe_r1 <= tx_ip_sync;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txoe_r2 <= 1'b0;
else
if(fs_ce) txoe_r2 <= txoe_r1;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txoe <= 1'b1;
else
if(fs_ce) txoe <= !(txoe_r1 | txoe_r2);
///////////////////////////////////////////////////////////////////
//
// Output Registers
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txdp <= 1'b1;
else
if(fs_ce) txdp <= phy_mode ?
(!append_eop_sync3 & sd_nrzi_o) :
sd_nrzi_o;
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txdn <= 1'b0;
else
if(fs_ce) txdn <= phy_mode ?
(!append_eop_sync3 & ~sd_nrzi_o) :
append_eop_sync3;
///////////////////////////////////////////////////////////////////
//
// Tx Statemashine
//
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) state <= IDLE;
else state <= next_state;
always @(state or TxValid_i or data_done or sft_done_e or eop_done or fs_ce)
begin
next_state = state;
tx_ready_d = 1'b0;
ld_sop_d = 1'b0;
ld_data_d = 1'b0;
ld_eop_d = 1'b0;
case(state) // synopsys full_case parallel_case
IDLE:
if(TxValid_i)
begin
ld_sop_d = 1'b1;
next_state = SOP;
end
SOP:
if(sft_done_e)
begin
tx_ready_d = 1'b1;
ld_data_d = 1'b1;
next_state = DATA;
end
DATA:
begin
if(!data_done && sft_done_e)
begin
ld_eop_d = 1'b1;
next_state = EOP1;
end
if(data_done && sft_done_e)
begin
tx_ready_d = 1'b1;
ld_data_d = 1'b1;
end
end
EOP1:
if(eop_done) next_state = EOP2;
EOP2:
if(!eop_done && fs_ce) next_state = WAIT;
WAIT:
if(fs_ce) next_state = IDLE;
endcase
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -