//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
// uart tasks:
|
// uart tasks:
|
// send_serial serial transmitter
|
// send_serial serial transmitter
|
// get_serial serial receiver
|
// get_serial serial receiver
|
//
|
//
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
|
|
/* Serial Parameters used for send_serial task and its callers. */
|
/* Serial Parameters used for send_serial task and its callers. */
|
`define PARITY_OFF 1'b0
|
`define PARITY_OFF 1'b0
|
`define PARITY_ON 1'b1
|
`define PARITY_ON 1'b1
|
`define PARITY_ODD 1'b0
|
`define PARITY_ODD 1'b0
|
`define PARITY_EVEN 1'b1
|
`define PARITY_EVEN 1'b1
|
`define NSTOPS_1 1'b0
|
`define NSTOPS_1 1'b0
|
`define NSTOPS_2 1'b1
|
`define NSTOPS_2 1'b1
|
`define BAUD_115200 3'b000
|
`define BAUD_115200 3'b000
|
`define BAUD_38400 3'b001
|
`define BAUD_38400 3'b001
|
`define BAUD_28800 3'b010
|
`define BAUD_28800 3'b010
|
`define BAUD_19200 3'b011
|
`define BAUD_19200 3'b011
|
`define BAUD_9600 3'b100
|
`define BAUD_9600 3'b100
|
`define BAUD_4800 3'b101
|
`define BAUD_4800 3'b101
|
`define BAUD_2400 3'b110
|
`define BAUD_2400 3'b110
|
`define BAUD_1200 3'b111
|
`define BAUD_1200 3'b111
|
`define NBITS_7 1'b0
|
`define NBITS_7 1'b0
|
`define NBITS_8 1'b1
|
`define NBITS_8 1'b1
|
// constants for status from get_serial task
|
// constants for status from get_serial task
|
`define RECEIVE_RESULT_OK 4'b1000
|
`define RECEIVE_RESULT_OK 4'b1000
|
`define RECEIVE_RESULT_FALSESTART 4'b0001
|
`define RECEIVE_RESULT_FALSESTART 4'b0001
|
`define RECEIVE_RESULT_BADPARITY 4'b0010
|
`define RECEIVE_RESULT_BADPARITY 4'b0010
|
`define RECEIVE_RESULT_BADSTOP 4'b0100
|
`define RECEIVE_RESULT_BADSTOP 4'b0100
|
|
|
// uart tasks global interfaces signals
|
// uart tasks global interfaces signals
|
reg serial_out; // transmit serial output
|
reg serial_out; // transmit serial output
|
reg serial_in; // receive serial input
|
reg serial_in; // receive serial input
|
reg [7:0] get_serial_data; // data received from serial
|
reg [7:0] get_serial_data; // data received from serial
|
reg [7:0] get_serial_status; // status of receive operation
|
reg [7:0] get_serial_status; // status of receive operation
|
|
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
// uart transmit task
|
// uart transmit task
|
//
|
//
|
// usage:
|
// usage:
|
// send_serial (data, baud_rate, parity_type, parity_on, stop_bits_num,
|
// send_serial (data, baud_rate, parity_type, parity_on, stop_bits_num,
|
// data_bit_num, baud_error);
|
// data_bit_num, baud_error);
|
// where:
|
// where:
|
// data data character for transmission
|
// data data character for transmission
|
// parity_type this is a flag indicating that parity should be even
|
// parity_type this is a flag indicating that parity should be even
|
// (either 'PARITY_ODD or 'PARITY_EVEN)
|
// (either 'PARITY_ODD or 'PARITY_EVEN)
|
// parity_on indicates that the parity is used
|
// parity_on indicates that the parity is used
|
// (either 'PARITY_OFF or 'PARITY_ON)
|
// (either 'PARITY_OFF or 'PARITY_ON)
|
// stop_bits_num number of stop bits (either NSTOPS_1 or NSTOPS_2)
|
// stop_bits_num number of stop bits (either NSTOPS_1 or NSTOPS_2)
|
// data_bit_num number of data bits (either NBITS_7 or NBITS_8)
|
// data_bit_num number of data bits (either NBITS_7 or NBITS_8)
|
// baud_error baud error in precentage (-5 is -5%)
|
// baud_error baud error in precentage (-5 is -5%)
|
//
|
//
|
|
|
task send_serial;
|
task send_serial;
|
// task input parameters
|
// task input parameters
|
input [7:0] inputchar;
|
input [7:0] inputchar;
|
input baud;
|
input baud;
|
input paritytype;
|
input paritytype;
|
input parityenable;
|
input parityenable;
|
input nstops;
|
input nstops;
|
input nbits;
|
input nbits;
|
input baud_error_factor;
|
input baud_error_factor;
|
// internal registers
|
// internal registers
|
reg nbits;
|
reg nbits;
|
reg parityenable;
|
reg parityenable;
|
reg paritytype;
|
reg paritytype;
|
reg [1:0] baud;
|
reg [1:0] baud;
|
reg nstops;
|
reg nstops;
|
integer baud_error_factor; // e.g. +5 means 5% too fast and -5 means 5% too slow
|
integer baud_error_factor; // e.g. +5 means 5% too fast and -5 means 5% too slow
|
reg [7:0] char;
|
reg [7:0] char;
|
reg [7:0] disp_char;
|
reg [7:0] disp_char;
|
reg parity_bit;
|
reg parity_bit;
|
integer bit_time;
|
integer bit_time;
|
integer num_of_bits;
|
integer num_of_bits;
|
// task implementation
|
// task implementation
|
begin
|
begin
|
char = inputchar;
|
char = inputchar;
|
parity_bit = 1'b0;
|
parity_bit = 1'b0;
|
// calculate bit time from input baud rate - this assumes a simulation resolution of 1ns
|
// calculate bit time from input baud rate - this assumes a simulation resolution of 1ns
|
case (baud)
|
case (baud)
|
`BAUD_115200: bit_time = 1000000000/(115200 + 1152*baud_error_factor);
|
`BAUD_115200: bit_time = 1000000000/(115200 + 1152*baud_error_factor);
|
// `BAUD_115200: bit_time = 40000000000/(115200 + 1152*baud_error_factor);
|
// `BAUD_115200: bit_time = 40000000000/(115200 + 1152*baud_error_factor);
|
`BAUD_38400: bit_time = 1000000000/(38400 + 384*baud_error_factor);
|
`BAUD_38400: bit_time = 1000000000/(38400 + 384*baud_error_factor);
|
`BAUD_28800: bit_time = 1000000000/(28800 + 288*baud_error_factor);
|
`BAUD_28800: bit_time = 1000000000/(28800 + 288*baud_error_factor);
|
`BAUD_19200: bit_time = 1000000000/(19200 + 192*baud_error_factor);
|
`BAUD_19200: bit_time = 1000000000/(19200 + 192*baud_error_factor);
|
`BAUD_9600: bit_time = 1000000000/(9600 + 96*baud_error_factor);
|
`BAUD_9600: bit_time = 1000000000/(9600 + 96*baud_error_factor);
|
`BAUD_4800: bit_time = 1000000000/(4800 + 48*baud_error_factor);
|
`BAUD_4800: bit_time = 1000000000/(4800 + 48*baud_error_factor);
|
`BAUD_2400: bit_time = 1000000000/(2400 + 24*baud_error_factor);
|
`BAUD_2400: bit_time = 1000000000/(2400 + 24*baud_error_factor);
|
`BAUD_1200: bit_time = 1000000000/(1200 + 12*baud_error_factor);
|
`BAUD_1200: bit_time = 1000000000/(1200 + 12*baud_error_factor);
|
endcase
|
endcase
|
|
|
// display info
|
// display info
|
disp_char = (char >= 8'h20) ? char : 8'hb0;
|
disp_char = (char >= 8'h20) ? char : 8'hb0;
|
$display ("Sending character 0x%h (\"%c\"), at %0d baud (err=%0d), %0d bits, %0s parity, %0d stops",
|
$display ("Sending character 0x%h (\"%c\"), at %0d baud (err=%0d), %0d bits, %0s parity, %0d stops",
|
(nbits == `NBITS_7) ? (char & 8'h7f) : char,
|
(nbits == `NBITS_7) ? (char & 8'h7f) : char,
|
(nbits == `NBITS_7) ? (disp_char & 8'h7f) : disp_char,
|
(nbits == `NBITS_7) ? (disp_char & 8'h7f) : disp_char,
|
1000000000/bit_time,
|
1000000000/bit_time,
|
baud_error_factor,
|
baud_error_factor,
|
(nbits == `NBITS_7) ? 7 : 8,
|
(nbits == `NBITS_7) ? 7 : 8,
|
(parityenable == `PARITY_OFF) ? "NONE" : (paritytype == `PARITY_EVEN) ? "EVEN" : "ODD",
|
(parityenable == `PARITY_OFF) ? "NONE" : (paritytype == `PARITY_EVEN) ? "EVEN" : "ODD",
|
(nstops == `NSTOPS_1) ? 1 : 2
|
(nstops == `NSTOPS_1) ? 1 : 2
|
);
|
);
|
|
|
// Start bit
|
// Start bit
|
serial_out = 1'b0; // Start bit.
|
serial_out = 1'b0; // Start bit.
|
#(bit_time);
|
#(bit_time);
|
|
|
// Output data bits
|
// Output data bits
|
num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
|
num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
|
repeat (num_of_bits)
|
repeat (num_of_bits)
|
begin
|
begin
|
serial_out = char[0];
|
serial_out = char[0];
|
#(bit_time);
|
#(bit_time);
|
char = {1'b0, char[7:1]};
|
char = {1'b0, char[7:1]};
|
end
|
end
|
|
|
// check if parity is enabled
|
// check if parity is enabled
|
if (parityenable == `PARITY_ON) begin
|
if (parityenable == `PARITY_ON) begin
|
parity_bit = (nbits == `NBITS_7) ? ^inputchar[6:0] : ^inputchar[7:0];
|
parity_bit = (nbits == `NBITS_7) ? ^inputchar[6:0] : ^inputchar[7:0];
|
// even parity
|
// even parity
|
if (paritytype == `PARITY_ODD)
|
if (paritytype == `PARITY_ODD)
|
parity_bit = ~parity_bit;
|
parity_bit = ~parity_bit;
|
|
|
serial_out = parity_bit;
|
serial_out = parity_bit;
|
#(bit_time);
|
#(bit_time);
|
end
|
end
|
|
|
// Stop bit.
|
// Stop bit.
|
serial_out = 1'b1;
|
serial_out = 1'b1;
|
#(bit_time);
|
#(bit_time);
|
// Second stop bit
|
// Second stop bit
|
if (nstops)
|
if (nstops)
|
#(bit_time);
|
#(bit_time);
|
end
|
end
|
endtask
|
endtask
|
|
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
// uart receive task
|
// uart receive task
|
//
|
//
|
// usage:
|
// usage:
|
// get_serial (baud_rate, parity_type, parity_on, stop_bits_num, data_bit_num);
|
// get_serial (baud_rate, parity_type, parity_on, stop_bits_num, data_bit_num);
|
// where:
|
// where:
|
// data data character for transmission
|
// data data character for transmission
|
// parity_type this is a flag indicating that parity should be even
|
// parity_type this is a flag indicating that parity should be even
|
// (either 'PARITY_ODD or 'PARITY_EVEN)
|
// (either 'PARITY_ODD or 'PARITY_EVEN)
|
// parity_on indicates that the parity is used
|
// parity_on indicates that the parity is used
|
// (either 'PARITY_OFF or 'PARITY_ON)
|
// (either 'PARITY_OFF or 'PARITY_ON)
|
// stop_bits_num number of stop bits (either NSTOPS_1 or NSTOPS_2)
|
// stop_bits_num number of stop bits (either NSTOPS_1 or NSTOPS_2)
|
// data_bit_num number of data bits (either NBITS_7 or NBITS_8)
|
// data_bit_num number of data bits (either NBITS_7 or NBITS_8)
|
//
|
//
|
task get_serial;
|
task get_serial;
|
// input parameters
|
// input parameters
|
input baud;
|
input baud;
|
input paritytype;
|
input paritytype;
|
input parityenable;
|
input parityenable;
|
input nstops;
|
input nstops;
|
input nbits;
|
input nbits;
|
// internal registers
|
// internal registers
|
reg nbits;
|
reg nbits;
|
reg parityenable;
|
reg parityenable;
|
reg paritytype;
|
reg paritytype;
|
reg [1:0] baud;
|
reg [1:0] baud;
|
reg nstops;
|
reg nstops;
|
integer bit_time;
|
integer bit_time;
|
reg expected_parity;
|
reg expected_parity;
|
integer num_of_bits;
|
integer num_of_bits;
|
// task implementation
|
// task implementation
|
begin
|
begin
|
// init receive globals
|
// init receive globals
|
get_serial_status = 0;
|
get_serial_status = 0;
|
get_serial_data = 0;
|
get_serial_data = 0;
|
|
|
// calculate bit time from input baud rate - this assumes a simulation resolution of 1ns
|
// calculate bit time from input baud rate - this assumes a simulation resolution of 1ns
|
case (baud)
|
case (baud)
|
`BAUD_115200: bit_time = 1000000000/115200;
|
`BAUD_115200: bit_time = 1000000000/115200;
|
`BAUD_38400: bit_time = 1000000000/38400;
|
`BAUD_38400: bit_time = 1000000000/38400;
|
`BAUD_28800: bit_time = 1000000000/28800;
|
`BAUD_28800: bit_time = 1000000000/28800;
|
`BAUD_19200: bit_time = 1000000000/19200;
|
`BAUD_19200: bit_time = 1000000000/19200;
|
`BAUD_9600: bit_time = 1000000000/9600;
|
`BAUD_9600: bit_time = 1000000000/9600;
|
`BAUD_4800: bit_time = 1000000000/4800;
|
`BAUD_4800: bit_time = 1000000000/4800;
|
`BAUD_2400: bit_time = 1000000000/2400;
|
`BAUD_2400: bit_time = 1000000000/2400;
|
`BAUD_1200: bit_time = 1000000000/1200;
|
`BAUD_1200: bit_time = 1000000000/1200;
|
endcase
|
endcase
|
|
|
// Assume OK until bad things happen.
|
// Assume OK until bad things happen.
|
get_serial_status = `RECEIVE_RESULT_OK;
|
get_serial_status = `RECEIVE_RESULT_OK;
|
|
|
// wait for start bit edge
|
// wait for start bit edge
|
@(negedge serial_in);
|
@(negedge serial_in);
|
|
|
// wait till center of start bit
|
// wait till center of start bit
|
#(bit_time/2);
|
#(bit_time/2);
|
|
|
// make sure its really a start bit
|
// make sure its really a start bit
|
if (serial_in != 0)
|
if (serial_in != 0)
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_FALSESTART;
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_FALSESTART;
|
else
|
else
|
begin
|
begin
|
// get all the data bits (7 or 8)
|
// get all the data bits (7 or 8)
|
num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
|
num_of_bits = (nbits == `NBITS_7) ? 7 : 8;
|
repeat (num_of_bits)
|
repeat (num_of_bits)
|
begin
|
begin
|
// wait till center
|
// wait till center
|
#(bit_time);
|
#(bit_time);
|
// sample a data bit
|
// sample a data bit
|
get_serial_data = {serial_in, get_serial_data[7:1]};
|
get_serial_data = {serial_in, get_serial_data[7:1]};
|
end
|
end
|
|
|
// If we are only expecting 7 bits, go ahead and right-justify what we have
|
// If we are only expecting 7 bits, go ahead and right-justify what we have
|
if (nbits == `NBITS_7)
|
if (nbits == `NBITS_7)
|
get_serial_data = {1'b0, get_serial_data[7:1]};
|
get_serial_data = {1'b0, get_serial_data[7:1]};
|
|
|
// wait for next bit to start
|
// wait for next bit to start
|
#(bit_time);
|
#(bit_time);
|
|
|
// now, we have either a parity bit, or a stop bit
|
// now, we have either a parity bit, or a stop bit
|
if (parityenable == `PARITY_ON) begin
|
if (parityenable == `PARITY_ON) begin
|
if (paritytype == `PARITY_EVEN)
|
if (paritytype == `PARITY_EVEN)
|
expected_parity = (nbits == `NBITS_7) ? (^get_serial_data[6:0]) :
|
expected_parity = (nbits == `NBITS_7) ? (^get_serial_data[6:0]) :
|
(^get_serial_data[7:0]);
|
(^get_serial_data[7:0]);
|
else
|
else
|
expected_parity = (nbits == `NBITS_7) ? (~(^get_serial_data[6:0])) :
|
expected_parity = (nbits == `NBITS_7) ? (~(^get_serial_data[6:0])) :
|
(~(^get_serial_data[7:0]));
|
(~(^get_serial_data[7:0]));
|
|
|
if (expected_parity != serial_in)
|
if (expected_parity != serial_in)
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADPARITY;
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADPARITY;
|
end
|
end
|
// wait for either 1 or 2 stop bits
|
// wait for either 1 or 2 stop bits
|
else begin
|
else begin
|
// this is a stop bit.
|
// this is a stop bit.
|
if (serial_in != 1)
|
if (serial_in != 1)
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
|
else
|
else
|
// that was cool. if 2 stops, then do this again
|
// that was cool. if 2 stops, then do this again
|
if (nstops)
|
if (nstops)
|
begin
|
begin
|
#(bit_time);
|
#(bit_time);
|
if (serial_in != 1)
|
if (serial_in != 1)
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
|
get_serial_status = get_serial_status | `RECEIVE_RESULT_BADSTOP;
|
end
|
end
|
#(bit_time/2);
|
|
end
|
end
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|