module host (D_, D, clk ) ;
inout D_, D;
input clk;
 
wire Din, D_in;
wire Dout, D_out;
reg En ;
reg out, out_2, out_1 ;
reg [7:0] nrzi_out ;
reg [4:0] crc5 ;
reg [2:0] bit_cnt ;
 
wire shift_out = nrzi_out[0];
 
initial begin
out = 1'b1 ;
crc5 = 5'h18 ; //dummy crc
En = 1'b0 ;
nrzi_out = 8'h00 ;
bit_cnt = 0 ;
end
 
assign D = (En) ? Dout : 1'bZ ;
assign D_ = (En) ? D_out : 1'bZ ;
 
assign Dout = out;
assign D_out = ~out ;
 
task send_token ;
input [7:0] pid ;
input [6:0] addr ;
input [3:0] ep ;
begin
@(negedge clk );
nrzi_out = 8'h80 ; // load sync
@(posedge clk );
En = 1'b1 ;
$display ("%0t: Send Token: %h Addr=%h Ep=%h", $time, pid, addr, ep);
// Wait for sync (only 1 is counted since first bit
// get toggled immediately )
repeat (7) @(posedge clk); #1;
 
nrzi_out = {pid}; //load pid
repeat (8) @(posedge clk); #1 //wait for pid
 
nrzi_out = {1'b0, addr};
repeat (7) @(posedge clk); #1; //wait for addr
 
nrzi_out = {4'h0, ep} ; // load ep
repeat (4) @(posedge clk); #1; // wait for ep
 
//nrzi_out = {3'b000, crc5[0], crc5[1], crc5[2], crc5[3], crc5[4]}; // load crc5
nrzi_out = {3'b000, crc5}; // load crc5
repeat (5) @(posedge clk); #1; // wait for crc5
 
// force se0 for 2 bits (eop = 2bits of se0 + 1 bit of idle)
// dont use inverted logic for D and D_, instead force
// zeros on both
force Dout = 0 ;
force D_out = 0 ;
nrzi_out = 8'hFF ;
repeat (2) @(posedge clk); #1; //wait for 2 bits of se0
force Dout = 1 ; // idle
force D_out = 0 ; // idle
 
// stop forcing zeros and send idle
release Dout ;
release D_out ;
out = 1'b1 ;
#0
repeat (1) @(posedge clk); #1;
 
En = 1'b0 ;
$display ("%0t: End of Token ", $time);
end
endtask
 
 
 
always @(posedge clk ) begin
if (En) begin
if (~shift_out ) begin
out = ~out ;
bit_cnt = 0 ;
end
else begin
out = out ;
bit_cnt = bit_cnt +1 ;
end
if (bit_cnt!= 7) begin
nrzi_out = nrzi_out >> 1 ;
end
else begin
$display ("%0t: host stuffing bit ",$time);
nrzi_out = nrzi_out >> 1 ;
out = ~out ;
end
end
end
 
 
 
 
endmodule