/* This is the main SIE module which combines the transmitter and the receiver
modules */
module main(reset,D, D_,clk,
addr_latch,endp_latch,pid_latch,crc5_latch,crc16_latch1,crc16_latch2,data_latch,
TX_DATA, TX_LOAD, TX_EN, send_eop);
 
inout D, D_ ;
input reset, clk;
output [7:0] pid_latch,crc16_latch1,crc16_latch2,data_latch;
output [3:0] endp_latch ;
output [6:0] addr_latch ;
output [4:0] crc5_latch ;
 
input [7:0] TX_DATA ;
input TX_EN, send_eop, TX_LOAD ;
 
 
wire Dout, D_out ;
 
assign D = (TX_EN ) ? Dout : 1'bZ ;
assign D_ = (TX_EN) ? D_out : 1'bZ ;
 
/***********************RX MAIN ******************************/
wire Din, D_in, rxd ;
 
//wire [7:0] pid_latch,crc16_latch1,crc16_latch2,data_latch;
//wire [4:0] crc5_latch;
//wire [6:0] addr_latch;
//wire [3:0] endp_latch;
/************** RX STATE MACHINE DECLARATIONS *************************/
 
reg enable_bit_unstuff ,loadep3,load7,loadcrc4,loadcrc15,loadaddr5,latch_pid,
latch_addr,latch_ep,latch_crc5,latch_data,latch_crc16,loaddata6,
got_syn,got_eop;
parameter idle=0,pid=1,pid2=2, pid_decode=3,pid_dec2=15, data_phase=4,crc_data=6,
eop=8,addr=9,crc_token=13,data_phase2=5,crc_data2=7,addr2=10,endp=11,
endp2=12,crc_token2=14;
reg [3:0] state,nextstate;
 
 
 
/************* RX COUNTER DECLARATIONS **********************************/
 
reg [3:0] LOADVALUE;
wire count0;
 
/*****************EOP DETECT DECLARATIONS ********************************/
 
reg eop_out_st;
reg [2:0] eop_state,eop_next_state;
parameter s0=0,s1=1,s2=2;
 
/**************** SYNC DETECT DECLARATIONS ********************************/
reg [2:0] syn_state,next_syn_state;
parameter sy0=0,sy1=1,sy2=2,sy3=3,sy4=4,sy5=5,sy6=6,sy7=7;
 
/***************** NRZI DECODER DECLARATIONS *******************************/
reg q;
wire nrzi_dec_out;
 
/****************** SERIAL TO PARALLEL CONVERTER DECLARATIONS ***************/
reg [7:0] shift_out;
 
/******************* BIT UNSTUFFER DECLARATIONS *****************************/
reg [2:0] unst_state,next_unst_state;
parameter sbun0=0,sbun1=1,sbun2=2,sbun3=3,sbun4=4,sbun5=5;
reg bito,unst_out,rx_dis;
 
/******************** LATCHS DECLARATIONS ***********************************/
reg [7:0] pid_latch,crc16_latch1, crc16_latch2,data_latch;
reg [4:0] crc5_latch;
reg [6:0] addr_latch;
reg [3:0] endp_latch;
 
/***************************************************************************/
 
 
assign rxd = (Din & ~D_in) ? 1'b1 : 1'b0 ;
assign Din = D ;
assign D_in = D_ ;
/********************* RX STATE MACHINE ************************************/
/* Module : Rx_State machine.
This module needed to generate control signals to latch different parts of
packet, to generate signal for the counter and disable/enable
bit-stuffer. The inputs are coming from the sync detect */
always @(posedge clk)
begin
if (~reset)
state <= idle ;
else
state <= nextstate ;
end
 
/*************************** enable bit unstuff logic **********************/
always @(posedge clk ) begin
if (~reset )
enable_bit_unstuff <= 1'b0 ;
else begin
if (got_syn )
enable_bit_unstuff <= 1'b1 ;
else if (got_eop )
enable_bit_unstuff <= 1'b0 ;
else
enable_bit_unstuff <= enable_bit_unstuff ;
end
end
 
/*********************** Rx state machine *******************************/
always @(state or got_syn or count0 or got_eop)
begin
case(state)
idle:
begin
if(got_syn) nextstate <= pid;
else nextstate <= idle;
end
pid:
begin
if(count0)begin
nextstate <= pid_dec2;
end
else begin
nextstate <= pid2;
end
end
 
pid2:
begin
if(count0)begin
nextstate <= pid_dec2;
end
else begin
nextstate <= pid2;
end
end
data_phase:
begin
if(count0)begin
nextstate <= crc_data;
end
else begin
nextstate <= data_phase2;
end
end
data_phase2:
begin
if(count0)begin
nextstate <= crc_data;
end
else begin
nextstate <= data_phase2;
end
end
addr:
begin
if(count0)begin
nextstate <= endp;
end
else begin
nextstate <= addr2;
end
end
addr2:
begin
if(count0)begin
nextstate <= endp;
end
else begin
nextstate <= addr2;
end
end
endp:
begin
if(count0)begin
nextstate <= crc_token;
end
else begin
nextstate <= endp2;
end
end
endp2:
begin
if(count0)begin
nextstate <= crc_token;
end
else begin
nextstate <= endp2;
end
end
crc_token:
begin
if(count0)begin
nextstate <= eop;
end
else begin
nextstate <= crc_token2;
end
end
crc_token2:
begin
if(count0)begin
nextstate <= eop;
end
else begin
nextstate <= crc_token2;
end
end
crc_data:
begin
if(count0)begin
nextstate <= eop;
end
else begin
nextstate <= crc_data2;
end
end
crc_data2:
begin
if(count0)begin
nextstate <= eop;
end
else begin
nextstate <= crc_data2;
end
end
pid_decode:
begin
if(pid_latch==8'hc3 | pid_latch==8'hd2)
nextstate <= data_phase;
else nextstate<=addr;
end
pid_dec2 :nextstate <= pid_decode;
eop:
begin
if (got_eop)
nextstate<=idle;
else
nextstate<=eop;
end
default : nextstate<= idle;
 
endcase
end
always @(posedge clk )
begin
if (~reset)
load7<=1'b0;
else begin
if (state == pid) begin
if ((~count0) | ~(state == pid2)) load7 <= 1'b1;
else load7 <= 1'b0;
end
else load7 <= 1'b0;
end
end
always @(posedge clk )
begin
if (~reset)
latch_pid<=1'b0;
else begin
if (state == pid2) begin
if (count0) latch_pid <= 1'b1;
else latch_pid <= 1'b0;
end
else latch_pid <=1'b0 ;
end
end
always @(posedge clk )
begin
if (~reset)
loaddata6<=1'b0;
else begin
if (state == data_phase) begin
if (count0 | (state == data_phase2)) loaddata6 <= 1'b0;
else loaddata6 <= 1'b1;
end
else loaddata6 <= 1'b0;
end
end
always @(posedge clk )
begin
if (~reset)
latch_data<=1'b0;
else begin
if (state == data_phase2) begin
if (count0) latch_data <= 1'b1;
else latch_data <= 1'b0;
end
else latch_data <=1'b0 ;
end
end
always @(posedge clk )
begin
if (~reset) begin
loadaddr5<=0;
loadep3<=1'b0;
loadcrc4<=1'b0;
loadcrc15<=1'b0;
latch_ep<=1'b0;
latch_addr<=1'b0;
latch_crc5<=1'b0;
latch_crc16<=1'b0;
end
else begin
if (state == addr) begin
if (count0 | (state == addr2)) loadaddr5 <= 1'b0;
else loadaddr5 <= 1'b1;
end
else loadaddr5 <= 1'b0;
if (state == addr2) begin
if (count0) latch_addr <= 1'b1;
else latch_addr <= 1'b0;
end
else latch_addr <=1'b0 ;
if (state == endp) begin
if (count0 | (state == endp2)) loadep3 <= 1'b0;
else loadep3 <= 1'b1;
end
else loadep3 <= 1'b0;
if (state == endp2) begin
if (count0) latch_ep <= 1'b1;
else latch_ep <= 1'b0;
end
else latch_ep <=1'b0 ;
if (state == crc_token) begin
if (count0 | (state == crc_token2)) loadcrc4 <= 1'b0;
else loadcrc4 <= 1'b1;
end
else loadcrc4 <= 1'b0;
if (state == crc_token2) begin
if (count0) latch_crc5 <= 1'b1;
else latch_crc5 <= 1'b0;
end
else latch_crc5 <=1'b0 ;
if (state == crc_data) begin
if (count0 | (state == crc_data2)) loadcrc15 <= 1'b0;
else loadcrc15 <= 1'b1;
end
else loadcrc15 <= 1'b0;
if (state == crc_data2) begin
if (count0) latch_crc16 <= 1'b1;
else latch_crc16 <= 1'b0;
end
else latch_crc16 <=1'b0;
end
end
/*********************** RX COUNTER BEGINS ************************/
/* Module : Rx_Counter.
This module counts down to 0 and sends an output
count0 = 1 for a given load value. The input to
this module comes from the Rx_state machine.
This module is used in the receiver */
always @(posedge clk)
if(~reset)
begin
LOADVALUE <= 0 ;
end
else
begin
if (load7)
LOADVALUE <= 4;
else if (loaddata6)
LOADVALUE <= 4;
else if (loadaddr5)
LOADVALUE <= 2;
else if (loadcrc15)
LOADVALUE <= 13;
else if (loadcrc4)
LOADVALUE <= 2;
else if (loadep3)
LOADVALUE <= 1;
else
LOADVALUE <= LOADVALUE-1;
end
 
assign count0 = LOADVALUE == 4'b0;
 
/***************** EOP DETECT BEGINS *************************************/
 
always @ (eop_state or Din or D_in)
begin
case (eop_state)
s0:
begin
if(Din | D_in)
begin
eop_next_state <= s0;
end
else
begin
eop_next_state <= s1;
end
end
s1:
begin
if(Din | D_in)
begin
eop_next_state <= s0;
end
else
begin
eop_next_state <= s2;
end
end
s2:
begin
if(Din & ~D_in)
begin
eop_next_state <= s0;
end
else
begin
eop_next_state <= s2;
end
end
default:
begin
eop_next_state <= s0 ;
end
endcase
end
always @(posedge clk)
begin
if (eop_state == s2) begin
if (Din & ~D_in) eop_out_st <= 1'b1;
else eop_out_st <= 1'b0;
end
else eop_out_st <=1'b0 ;
end
/*_________________________________________________*/
 
always @ (posedge clk)
if(~reset)
begin
eop_state <= 0;
got_eop <=0;
end
else
begin
eop_state <= eop_next_state;
got_eop <= eop_out_st;
end
/**************** SYNC BIT DETECT BEGINS *********************************/
 
always @ (syn_state or rxd) begin
case (syn_state)
sy0:
begin
if(rxd)
begin
next_syn_state <= sy0;
end
else
begin
next_syn_state <= sy1;
end
end
sy1:
begin
if(rxd)
begin
next_syn_state <= sy2;
end
else
begin
next_syn_state <= sy1;
end
end
sy2:
begin
if(rxd)
begin
next_syn_state <= sy0;
end
else
begin
next_syn_state <= sy3;
end
end
sy3:
begin
if(rxd)
begin
next_syn_state <= sy4;
end
else
begin
next_syn_state <= sy1;
end
end
sy4:
begin
if(rxd)
begin
next_syn_state <= sy0;
end
else
begin
next_syn_state <= sy5;
end
end
sy5:
begin
if(rxd)
begin
next_syn_state <= sy6;
end
else
begin
next_syn_state <= sy1;
end
end
sy6:
begin
if(rxd)
begin
next_syn_state <= sy0;
end
else
begin
next_syn_state <= sy7;
end
end
sy7:
begin
if(rxd)
begin
next_syn_state <= sy6;
end
else
begin
next_syn_state <= sy1;
end
end
endcase
end
always @(posedge clk)
begin
if ((syn_state == sy7) && (~rxd)) got_syn <=1'b1;
else got_syn <=1'b0;
end
 
always @ (posedge clk)
if(~reset)
begin
syn_state <= sy0;
end
else
syn_state <= next_syn_state;
/****************** NRZI DECODER BEGINS ************************************/
 
always@(posedge clk)
begin
q<=rxd;
end
assign #1 nrzi_dec_out=~(q^rxd);
 
/*********************SERIAL TO PARALLEL CONVERTER BEGINS ******************/
always @(posedge clk)
begin
if(~reset)
shift_out[7:0]<=0;
else
begin
if(~rx_dis)
shift_out[7:0] <= {nrzi_dec_out,shift_out[7:1]};
else
shift_out[7:0]<=shift_out[7:0];
end
end
 
/****************** BIT UNSTUFFER BEGINS **********************************/
/* Module : Bit Unstuffer
The zero that has been stuffed by the bit stuffer is removed. When the
disble goes high the last bit of the input remains the same for the
next clock cycle, thus restoring the 1 which was stuffed. */
always @ (unst_state or nrzi_dec_out) begin
case (unst_state)
sbun0:
begin
if(nrzi_dec_out)
begin
next_unst_state <= sbun1;
end
else
begin
next_unst_state <= sbun0;
end
end
sbun1:
begin
if(nrzi_dec_out)
begin
next_unst_state <= sbun2;
end
else
begin
next_unst_state <= sbun0;
end
end
sbun2:
begin
if(nrzi_dec_out)
begin
next_unst_state <= sbun3;
end
else
begin
next_unst_state <= sbun0;
end
end
sbun3:
begin
if(nrzi_dec_out)
begin
next_unst_state <= sbun4;
end
else
begin
next_unst_state <= sbun0;
end
end
sbun4:
begin
if(nrzi_dec_out)
begin
next_unst_state <= sbun5;
end
else
begin
next_unst_state <= sbun0;
end
end
sbun5:
begin
if(nrzi_dec_out)
begin
next_unst_state <= sbun0;
end
else
begin
next_unst_state <= sbun0;
end
end
default : begin
next_unst_state <= sbun0 ;
end
endcase
end
always @ (posedge clk)
begin
if ((unst_state == sbun5) && (nrzi_dec_out))
unst_out<= 1'b1;
else
unst_out<= 1'b0;
end
always @ (posedge clk)
begin
if (~reset)
begin
unst_state<=0;
rx_dis=0;
end
else
begin
if (enable_bit_unstuff)
unst_state <= next_unst_state;
else
unst_state <= 0 ;
rx_dis=unst_out;
end
end
always @ (posedge clk)
begin
if (~reset)
bito<=0;
else
bito<=nrzi_dec_out;
end
/************************ LATCHS BEGINS **********************************/
always @(posedge clk)
begin
if (latch_data) data_latch <= shift_out;
else data_latch <= data_latch;
if (latch_pid) pid_latch <= shift_out;
else pid_latch <= pid_latch;
if (latch_addr) addr_latch <= shift_out[7:1];
else addr_latch <= addr_latch;
if (latch_ep) endp_latch <= shift_out[7:4];
else endp_latch <= endp_latch;
if (latch_crc5) crc5_latch <= shift_out[7:3];
else crc5_latch <= crc5_latch;
if (latch_crc16) begin
crc16_latch2 <= shift_out;
crc16_latch1 <= crc16_latch2;
end
else begin
crc16_latch1 <= crc16_latch1;
crc16_latch2 <= crc16_latch2;
end
end
 
/********************END OF RX MAIN ******************************/
 
 
/*********************TX MAIN *********************************/
reg dis,nrzi_b;
reg [2:0] bit_state,next_bit_state;
parameter sb0=0,sb1=1,sb2=2,sb3=3,sb4=4,sb5=5;
 
reg nrzi_out;
reg [7:0] out_reg;
 
wire ptos_b;
 
//wire nrzi_out;
 
assign Dout = nrzi_out & ~send_eop ;
assign D_out = ~nrzi_out & ~send_eop ;
 
/**************** BIT STUFFER ********************************/
 
always @ (bit_state or ptos_b) begin
case (bit_state)
sb0:
begin
if(ptos_b)
begin
next_bit_state <= sb1;
end
else
begin
next_bit_state <= sb0;
end
end
sb1:
begin
if(ptos_b)
begin
next_bit_state <= sb2;
end
else
begin
next_bit_state <= sb0;
end
end
sb2:
begin
if(ptos_b)
begin
next_bit_state <= sb3;
end
else
begin
next_bit_state <= sb0;
end
end
sb3:
begin
if(ptos_b)
begin
next_bit_state <= sb4;
end
else
begin
next_bit_state <= sb0;
end
end
sb4:
begin
if(ptos_b)
begin
next_bit_state <= sb5;
end
else
begin
next_bit_state <= sb0;
end
end
sb5:
begin
if(ptos_b)
begin
next_bit_state <= sb0;
end
else
begin
next_bit_state <= sb0;
end
end
default :
begin
next_bit_state <=sb0 ;
end
endcase
end
always @ (posedge clk)
begin
if ((bit_state == sb5) && (ptos_b))
dis <= 1'b1;
else
dis <= 1'b0;
end
always @ (posedge clk)
if(~reset)
begin
bit_state<=sb0;
end
else
begin
bit_state <= next_bit_state;
end
always @ (posedge clk)
if(~reset)
begin
nrzi_b<=0;
end
else
begin
if(ptos_b & dis)
nrzi_b <= 0;
else
nrzi_b <= ptos_b;
end
/*************************** NRZI ENCODER BEGINS **************************/
 
always @(posedge clk)
if(~reset)
begin
nrzi_out<=1;
end
else
begin
if(nrzi_b)
nrzi_out<=nrzi_out;
else
nrzi_out<=~nrzi_out;
end
/************************** PARALLEL TO SERIAL CONVERTER BEGINS *************/
 
assign ptos_b=out_reg[0];
always @(posedge clk)
if(~reset)
begin
out_reg<=8'h00;
end
else
begin
if(~dis)
begin
if(TX_LOAD) begin
out_reg<=TX_DATA;
end
else begin
out_reg<=out_reg >> 1;
end
end
else out_reg <= out_reg;
end
 
/******************** END OF TX MAIN ***************************/
endmodule