This module is used to draw strings of characters to the serial output port, one character at a time. The module accepts only upper case characters (A-Z), digits (0-9) and space (“ ”). A null character (0) will not be drawn, and all other ASCII values are drawn as a solid rectangle.
There are several different ways to construct strings in SystemVerilog. For example, the following are all equivalent:
logic [39:0] char_string; assign char_string = "HELLO";
logic [39:0] char_string; assign char_string = 40'h48454C4C4F;
logic [39:0] char_string; assign char_string = {"H", "E", "L", "L", "O"};
logic [39:0] char_string; assign char_string = {8'h48, 8'h45, 8'h4C, 8'h4C, 8'h4F};
Module Name = CharDrawer_serial | |||
---|---|---|---|
Parameter | Default Value | Description | |
MAX_CHARS | 16 | The length of the string that the module can display. | |
Port Name | Direction | Width | Description |
clk | Input | 1 | 100 MHz Clock |
reset | Input | 1 | Active-high reset |
enable | Input | 1 | Raise this signal to start drawing. The drawing will continue until finished. To draw a new string you must lower and then raise this signal. |
done | Output | 1 | Active-high, indicating that the string is done drawing |
tx | Output | 1 | The serial out signal |
string_in | Input | MAX_CHARS * 8 | ASCII character string to draw, most-significant byte is drawn first. |
Click the link below to download the CharDrawer_serial.sv file.
module CharDrawer_serial # (parameter MAX_CHARS = 16)( input wire logic clk, // Clock input wire logic reset, // Active-high reset input wire logic enable, // Start drawing output logic done, // Done drawing output logic tx, // Serial out input wire logic [(MAX_CHARS * 8) - 1:0] string_in // ASCII character string to draw // MSB is drawn first ); logic clrCnt, incCnt, send, sent; logic[3:0] cnt; logic[7:0] din; // State Machine typedef enum logic[1:0] {ST_WAIT, ST_WAIT_SENT, ST_SENT, ST_DONE, ERR='X} StateType; StateType cs, ns; assign din = (cnt==0)?string_in[127:120]: (cnt==1)?string_in[119:112]: (cnt==2)?string_in[111:104]: (cnt==3)?string_in[103:96]: (cnt==4)?string_in[95:88]: (cnt==5)?string_in[87:80]: (cnt==6)?string_in[79:72]: (cnt==7)?string_in[71:64]: (cnt==8)?string_in[63:56]: (cnt==9)?string_in[55:48]: (cnt==10)?string_in[47:40]: (cnt==11)?string_in[39:32]: (cnt==12)?string_in[31:24]: (cnt==13)?string_in[23:16]: (cnt==14)?string_in[15:8]: string_in[7:0]; ////////////////////// Counter //////////////////// always_ff @(posedge clk) if (clrCnt) cnt <= 0; else if (incCnt) cnt <= cnt + 1; ////////////////////////////////// State Machine ////////////////////////////////// always_ff @(posedge clk) cs <= ns; always_comb begin ns = ERR; send = 0; clrCnt = 0; incCnt = 0; done = 0; if (reset) ns = ST_WAIT; else case (cs) ST_WAIT: begin clrCnt = 1; if (enable) ns = ST_WAIT_SENT; else ns = ST_WAIT; end ST_WAIT_SENT: begin send = 1; if (sent) ns = ST_SENT; else ns = ST_WAIT_SENT; end ST_SENT: begin if (~sent && cnt != 15) begin incCnt = 1; ns = ST_WAIT_SENT; end else if (~sent && cnt == 15) ns = ST_DONE; else ns = ST_SENT; end ST_DONE: begin done = 1; if (~enable) ns = ST_WAIT; else ns = ST_DONE; end default: ns = ERR; endcase end ///// The UART Tx tx TX(.clk(clk), .Reset(reset), .Send(send), .Din(din), .Sent(sent), .Sout(tx)); endmodule