| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- `timescale 1ns/1ps
- // -----------------------------------------------------------------------------
- // 16-byte UART Trace packet transmitter.
- //
- // This intentionally follows the packet format used by the user's previous
- // EF2L45 UART Trace project:
- //
- // Byte0 A5
- // Byte1 5A
- // Byte2 packet type
- // Byte3-4 sequence (big-endian)
- // Byte5-6 event_id (big-endian)
- // Byte7-10 timestamp (big-endian)
- // Byte11-14 data (big-endian)
- // Byte15 CRC-8
- //
- // CRC-8:
- // polynomial = 0x07
- // init = 0x00
- // covers bytes 2..14
- //
- // For this firmware packet_type is normally 0x82 (TRACE).
- // -----------------------------------------------------------------------------
- module trace_packet_tx #(
- parameter integer CLOCK_HZ = 25_000_000,
- parameter integer BAUD = 115_200
- )(
- input wire clk,
- input wire reset_n,
- input wire start,
- input wire [7:0] packet_type,
- input wire [15:0] seq,
- input wire [15:0] event_id,
- input wire [31:0] timestamp,
- input wire [31:0] data,
- output wire uart_tx,
- output reg busy
- );
- reg uart_start;
- reg [7:0] uart_data;
- wire uart_busy;
- reg [7:0] type_latched;
- reg [15:0] seq_latched;
- reg [15:0] event_latched;
- reg [31:0] time_latched;
- reg [31:0] data_latched;
- reg [4:0] byte_index;
- reg [7:0] crc_reg;
- localparam [1:0]
- S_IDLE = 2'd0,
- S_SEND = 2'd1,
- S_WAIT = 2'd2;
- reg [1:0] state;
- uart_tx #(
- .CLOCK_HZ(CLOCK_HZ),
- .BAUD(BAUD)
- ) u_uart_tx (
- .clk (clk),
- .reset_n(reset_n),
- .start (uart_start),
- .data (uart_data),
- .tx (uart_tx),
- .busy (uart_busy)
- );
- function [7:0] crc8_next;
- input [7:0] crc_in;
- input [7:0] data_in;
- integer i;
- reg [7:0] c;
- begin
- c = crc_in ^ data_in;
- for (i = 0; i < 8; i = i + 1) begin
- if (c[7])
- c = (c << 1) ^ 8'h07;
- else
- c = (c << 1);
- end
- crc8_next = c;
- end
- endfunction
- function [7:0] packet_byte;
- input [4:0] idx;
- begin
- case (idx)
- 5'd0: packet_byte = 8'hA5;
- 5'd1: packet_byte = 8'h5A;
- 5'd2: packet_byte = type_latched;
- 5'd3: packet_byte = seq_latched[15:8];
- 5'd4: packet_byte = seq_latched[7:0];
- 5'd5: packet_byte = event_latched[15:8];
- 5'd6: packet_byte = event_latched[7:0];
- 5'd7: packet_byte = time_latched[31:24];
- 5'd8: packet_byte = time_latched[23:16];
- 5'd9: packet_byte = time_latched[15:8];
- 5'd10: packet_byte = time_latched[7:0];
- 5'd11: packet_byte = data_latched[31:24];
- 5'd12: packet_byte = data_latched[23:16];
- 5'd13: packet_byte = data_latched[15:8];
- 5'd14: packet_byte = data_latched[7:0];
- default: packet_byte = 8'h00;
- endcase
- end
- endfunction
- reg [7:0] current_byte;
- always @(posedge clk or negedge reset_n) begin
- if (!reset_n) begin
- uart_start <= 1'b0;
- uart_data <= 8'd0;
- type_latched <= 8'd0;
- seq_latched <= 16'd0;
- event_latched <= 16'd0;
- time_latched <= 32'd0;
- data_latched <= 32'd0;
- byte_index <= 5'd0;
- crc_reg <= 8'd0;
- current_byte <= 8'd0;
- state <= S_IDLE;
- busy <= 1'b0;
- end else begin
- uart_start <= 1'b0;
- case (state)
- S_IDLE: begin
- busy <= 1'b0;
- if (start) begin
- type_latched <= packet_type;
- seq_latched <= seq;
- event_latched <= event_id;
- time_latched <= timestamp;
- data_latched <= data;
- byte_index <= 5'd0;
- crc_reg <= 8'd0;
- busy <= 1'b1;
- state <= S_SEND;
- end
- end
- S_SEND: begin
- busy <= 1'b1;
- if (!uart_busy) begin
- if (byte_index == 5'd15)
- current_byte = crc_reg;
- else
- current_byte = packet_byte(byte_index);
- uart_data <= current_byte;
- uart_start <= 1'b1;
- if ((byte_index >= 5'd2) &&
- (byte_index <= 5'd14))
- crc_reg <= crc8_next(crc_reg, current_byte);
- state <= S_WAIT;
- end
- end
- S_WAIT: begin
- busy <= 1'b1;
- // Wait until the just-launched UART byte has fully left.
- if (!uart_busy && !uart_start) begin
- if (byte_index == 5'd15) begin
- busy <= 1'b0;
- state <= S_IDLE;
- end else begin
- byte_index <= byte_index + 1'b1;
- state <= S_SEND;
- end
- end
- end
- default: begin
- busy <= 1'b0;
- state <= S_IDLE;
- end
- endcase
- end
- end
- endmodule
|