OpenCores
URL https://opencores.org/ocsvn/socgen/socgen/trunk

Subversion Repositories socgen

[/] [socgen/] [trunk/] [common/] [opencores.org/] [cde/] [ip/] [serial/] [rtl/] [verilog/] [serial_xmit.v] - Rev 131

Compare with Previous | Blame | View Log

module 
cde_serial_xmit
#(parameter   WIDTH=8,   // Number of data bits
  parameter   SIZE=4     // binary size of shift_cnt, must be able to hold  WIDTH + 4 states       
 )  
 
 
(
input  wire              clk,
input  wire              reset,
input  wire              edge_enable,                 // one pulse per bit time for data rate timing
input  wire              parity_enable,               // 0 = no parity bit sent, 1= parity bit sent
input  wire              parity_type,                 // 0= odd,1=even
input  wire              parity_force,                // force parity_type
input  wire              load,                        // start transmiting data
input  wire              start_value,                 // value out at start bit time
input  wire              stop_value,                  // value out for stop bit also used for break
input  wire [WIDTH-1:0]  data,                        // data byte
 
output  reg              buffer_empty,                // ready for next byte
output  reg              ser_out                      // to pad_ring
                         );
 
reg [SIZE-1:0] 	         shift_cnt;
reg [WIDTH-1:0] 	 shift_buffer;
reg 	  	         parity_calc;
reg                      delayed_edge_enable;
 
 
//
//   shift_cnt controls the serial bit out
//  
//   0           Start bit  
//   1-> WIDTH   Data bit lsb first
//   WIDTH+1     Parity bit if enabled
//   2^SIZE-1    Last stop bit and idle
 
always@(posedge clk)
  if(reset || buffer_empty)                                        shift_cnt   <= {SIZE{1'b1}};
  else
  if(!edge_enable)                                                 shift_cnt   <= shift_cnt;
  else
  if(( shift_cnt ==  {SIZE{1'b1}}  ) &&  ! buffer_empty )          shift_cnt   <= {SIZE{1'b0}};
  else
  if ( shift_cnt == WIDTH)               
    case(parity_enable)        
      (1'b0):                                                      shift_cnt   <= {SIZE{1'b1}};
      (1'b1):                                                      shift_cnt   <= shift_cnt + 1'b1;
    endcase // case ({two_stop_enable,parity_enable})
  else
  if ( shift_cnt == (WIDTH+1))                                     shift_cnt   <= {SIZE{1'b1}};
  else                                                             shift_cnt   <= shift_cnt + 1'b1;
 
//
//    
//   Clear buffer_empty upon load pulse
//   set it back at the start of the final stop pulse
//   if load happens BEFORE the next edge_enable then data transfer will have no pauses 
//   logic ensures that having load happen on a edge_enable will work
//   
 
always@(posedge clk)
   if(reset)                                                       delayed_edge_enable <= 1'b0;
   else                                                            delayed_edge_enable <= edge_enable && ! load;
 
 
always@(posedge clk)
if(reset)                                                          buffer_empty <= 1'b1;
else
if(load)                                                           buffer_empty <= 1'b0;
else
if((shift_cnt == {SIZE{1'b1}}) && delayed_edge_enable)    
                                                                   buffer_empty <= 1'b1;
else                                                               buffer_empty <= buffer_empty;
 
 
 
 
 
//
//
//   load shift_buffer during start_bit
//   shift down every bit
//   
//   
always@(posedge clk)
  if(reset)                                                        shift_buffer <= {WIDTH{1'b0}};
  else
  if(load)                                                         shift_buffer <= data;
  else
  if(!edge_enable)                                                 shift_buffer <= shift_buffer;
  else
  if(shift_cnt == {SIZE{1'b1}})                                    shift_buffer <= shift_buffer;
  else
  if(shift_cnt == {SIZE{1'b0}})                                    shift_buffer <= shift_buffer;
  else                                                             shift_buffer <= {1'b0,shift_buffer[WIDTH-1:1]};
 
 
 
 
 
 
//
//
//   calculate parity on the fly
//   seed reg with 0 for odd and 1 for even
//   force reg to 0 or 1 if needed  
//   
always@(posedge clk)
  if(reset)                                                        parity_calc <= 1'b0;
  else
  if(!edge_enable)                                                 parity_calc <= parity_calc;
  else
  if(parity_force || (shift_cnt == {SIZE{1'b0}}))                  parity_calc <= parity_type;
  else                                                             parity_calc <= parity_calc ^ shift_buffer[0];
 
 
//   send start_bit,data,parity and stop  based on shift_cnt
 
 
   always@(posedge clk)
     if(reset)                                                     ser_out <= stop_value;
     else
     if( shift_cnt == {SIZE{1'b0}} )                               ser_out <= start_value;
     else
     if( shift_cnt == {SIZE{1'b1}} )                               ser_out <= stop_value;
     else
     if( shift_cnt == ({SIZE{1'b1}}+1'b1) )                        ser_out <= stop_value;
     else
     if( shift_cnt == (WIDTH+1) )                                  ser_out <= parity_calc;
     else                                                          ser_out <= shift_buffer[0];
 
 
endmodule
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.