mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
328 lines
9.2 KiB
Systemverilog
Executable File
328 lines
9.2 KiB
Systemverilog
Executable File
//------------------------------------------------------------------------------
|
|
// uart_debug_printer.sv
|
|
// published as part of https://github.com/pConst/basic_verilog
|
|
// Konstantin Pavlov, pavlovconst@gmail.com
|
|
//------------------------------------------------------------------------------
|
|
|
|
// INFO ------------------------------------------------------------------------
|
|
// Debug data printer to UART terminal
|
|
// This particular module prints out one R/W bit and two 32-bit words in HEX format
|
|
// Could be easily adapted for other data formats
|
|
//
|
|
// Features:
|
|
// - fifo-like input interface
|
|
// - built-in UART transmitter
|
|
// - compatible with all sorts of UART-to-USB dongles
|
|
//
|
|
|
|
|
|
/* --- INSTANTIATION TEMPLATE BEGIN ---
|
|
|
|
uart_debug_printer #(
|
|
.CLK_HZ( 100_000_000 ),
|
|
.BAUD( 115200 )
|
|
) UP (
|
|
.clk( ),
|
|
.anrst( ),
|
|
|
|
.empty( ),
|
|
.r_req( ),
|
|
.r_rnw( ), // fifo data, 1 bit
|
|
.r_addr( ), // fifo data, 32 bit
|
|
.r_data( ), // fifo data, 32 bit
|
|
|
|
.uart_txd( )
|
|
);
|
|
|
|
--- INSTANTIATION TEMPLATE END ---*/
|
|
|
|
|
|
// synopsys translate_off
|
|
`define SIMULATION yes
|
|
// synopsys translate_on
|
|
|
|
module uart_debug_printer #( parameter
|
|
CLK_HZ = 100_000_000,
|
|
BAUD = 115200
|
|
)(
|
|
input clk, // clock 100MHz
|
|
input anrst, // async reset
|
|
|
|
// fifo output
|
|
input empty, // data valid flag
|
|
output logic r_req = 1'b0, // data request acknowledge
|
|
input r_rnw, // read/nwrite bit
|
|
input [31:0] r_addr, // first 32 bit word
|
|
input [31:0] r_data, // second 32 bit word
|
|
|
|
// UART TX
|
|
output uart_txd // UART tx pin
|
|
);
|
|
|
|
logic tx_start = 1'b0;
|
|
logic tx_busy;
|
|
|
|
// character sequencer
|
|
logic [7:0] seq_cntr = '0;
|
|
logic [7:0] tx_char = '0;
|
|
always_ff @( posedge clk or negedge anrst ) begin
|
|
if ( ~anrst ) begin
|
|
r_req = 1'b0;
|
|
tx_start = 1'b0;
|
|
|
|
seq_cntr[7:0] <= '0;
|
|
tx_char[7:0] <= '0;
|
|
end else begin
|
|
case ( seq_cntr[7:0] )
|
|
|
|
8'd0: begin
|
|
if( ~empty && ~tx_busy ) begin
|
|
tx_char[7:0] <= (r_rnw)?(8'd82):(8'd87); // "R"/"W" symbol
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd1: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= 8'd32; // "_" divider symbol =======================
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
|
|
|
|
8'd2: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[31:28]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd3: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[27:24]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd4: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[23:20]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd5: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[19:16]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd6: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= 8'd95; // "_" symbol
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd7: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[15:12]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd8: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[11:8]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd9: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[7:4]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd10: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_addr[3:0]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
|
|
8'd11: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= 8'd32; // "-" divider symbol =======================
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
|
|
8'd12: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[31:28]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd13: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[27:24]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd14: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[23:20]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd15: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[19:16]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd16: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= 8'd95; // "_" symbol
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd17: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[15:12]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd18: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[11:8]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd19: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[7:4]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
8'd20: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= hex2ascii(r_data[3:0]);
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
|
|
8'd21: begin
|
|
if( ~tx_start && ~tx_busy ) begin
|
|
tx_char[7:0] <= 8'd13; // "CR" symbol
|
|
seq_cntr[7:0] <= seq_cntr[7:0] + 1'b1;
|
|
r_req <= 1'b1; // fifo data ack begin
|
|
tx_start <= 1'b1;
|
|
end else begin
|
|
tx_start <= 1'b0;
|
|
end
|
|
end
|
|
|
|
8'd22: begin
|
|
if( ~tx_busy ) begin
|
|
tx_start <= 1'b0;
|
|
seq_cntr[7:0] <= '0;
|
|
end
|
|
r_req <= 1'b0; // fifo data ack end
|
|
end
|
|
|
|
default : seq_cntr[7:0] <= '0;
|
|
endcase
|
|
|
|
end
|
|
end
|
|
|
|
uart_tx #(
|
|
`ifdef SIMULATION
|
|
.CLK_HZ( 100 ),
|
|
.BAUD( 10 )
|
|
`else
|
|
.CLK_HZ( CLK_HZ ), // in Hertz
|
|
.BAUD( BAUD ) // max. BAUD is CLK_HZ / 2
|
|
`endif
|
|
) uart_tx_b (
|
|
.clk( clk ),
|
|
.nrst( 1'b1 ),
|
|
//.tx_do_sample( ),
|
|
.tx_data( tx_char[7:0] ),
|
|
.tx_start( tx_start ),
|
|
.tx_busy( tx_busy ),
|
|
.txd( uart_txd )
|
|
);
|
|
|
|
|
|
function [7:0] hex2ascii(
|
|
input [3:0] hex
|
|
);
|
|
if( hex[3:0] < 4'hA ) begin
|
|
hex2ascii[7:0] = hex[3:0] + 8'd48; // 0 hex -> 48 ascii
|
|
end else begin
|
|
hex2ascii[7:0] = hex[3:0] + 8'd55; // A hex -> 65 ascii
|
|
end // if
|
|
endfunction
|
|
|
|
endmodule
|
|
|