URL
https://opencores.org/ocsvn/socgen/socgen/trunk
Subversion Repositories socgen
[/] [socgen/] [trunk/] [common/] [opencores.org/] [cde/] [ip/] [serial/] [rtl/] [verilog/] [serial_xmit] - Rev 134
Compare with Previous | Blame | View Log
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];