mirror of https://github.com/openXC7/prjxray.git
162 lines
4.0 KiB
Verilog
162 lines
4.0 KiB
Verilog
`default_nettype none
|
|
|
|
// ============================================================================
|
|
|
|
module message_formatter #
|
|
(
|
|
parameter WIDTH = 24, // Word length in bits. MUST be a multiply of 4
|
|
parameter COUNT = 2, // Word count
|
|
parameter TX_INTERVAL = 4 // Character transmission interval
|
|
)
|
|
(
|
|
// Clock and reset
|
|
input wire CLK,
|
|
input wire RST,
|
|
|
|
// Data input
|
|
input wire I_STB,
|
|
input wire [(WIDTH*COUNT)-1:0] I_DAT,
|
|
|
|
// ASCII output
|
|
output wire O_STB,
|
|
output wire [7:0] O_DAT
|
|
);
|
|
|
|
// ============================================================================
|
|
|
|
// Total input data word width
|
|
localparam TOTAL_WIDTH = WIDTH * COUNT;
|
|
|
|
// ============================================================================
|
|
// FSM states
|
|
integer fsm;
|
|
|
|
localparam FSM_IDLE = 'h00;
|
|
localparam FSM_TX_HEX = 'h11;
|
|
localparam FSM_TX_CR = 'h21;
|
|
localparam FSM_TX_LF = 'h22;
|
|
localparam FSM_TX_SEP = 'h31;
|
|
|
|
// ============================================================================
|
|
// TX interval counter
|
|
reg [24:0] tx_dly_cnt;
|
|
reg tx_req;
|
|
wire tx_rdy;
|
|
|
|
always @(posedge CLK)
|
|
if (RST)
|
|
tx_dly_cnt <= -1;
|
|
else if (!tx_rdy)
|
|
tx_dly_cnt <= tx_dly_cnt - 1;
|
|
else if ( tx_rdy && tx_req)
|
|
tx_dly_cnt <= TX_INTERVAL - 2;
|
|
|
|
assign tx_rdy = tx_dly_cnt[24];
|
|
|
|
always @(posedge CLK)
|
|
if (RST)
|
|
tx_req <= 1'b0;
|
|
else case (fsm)
|
|
|
|
FSM_TX_HEX: tx_req <= 1'b1;
|
|
FSM_TX_SEP: tx_req <= 1'b1;
|
|
FSM_TX_CR: tx_req <= 1'b1;
|
|
FSM_TX_LF: tx_req <= 1'b1;
|
|
|
|
default: tx_req <= 1'b0;
|
|
|
|
endcase
|
|
|
|
// ============================================================================
|
|
// Word and char counter
|
|
reg [7:0] char_cnt;
|
|
reg [7:0] word_cnt;
|
|
|
|
always @(posedge CLK)
|
|
if (fsm == FSM_IDLE || fsm == FSM_TX_SEP)
|
|
char_cnt <= (WIDTH/4) - 1;
|
|
else if (tx_rdy && fsm == FSM_TX_HEX)
|
|
char_cnt <= char_cnt - 1;
|
|
|
|
always @(posedge CLK)
|
|
if (fsm == FSM_IDLE)
|
|
word_cnt <= COUNT - 1;
|
|
else if (tx_rdy && fsm == FSM_TX_SEP)
|
|
word_cnt <= word_cnt - 1;
|
|
|
|
// ============================================================================
|
|
// Data shift register
|
|
reg [TOTAL_WIDTH-1:0] sr_reg;
|
|
wire [3:0] sr_dat;
|
|
|
|
always @(posedge CLK)
|
|
if (fsm == FSM_IDLE && I_STB)
|
|
sr_reg <= I_DAT;
|
|
else if (fsm == FSM_TX_HEX && tx_rdy)
|
|
sr_reg <= sr_reg << 4;
|
|
|
|
assign sr_dat = sr_reg[TOTAL_WIDTH-1:TOTAL_WIDTH-4];
|
|
|
|
// ============================================================================
|
|
// Control FSM
|
|
always @(posedge CLK)
|
|
if (RST)
|
|
fsm <= FSM_IDLE;
|
|
else case (fsm)
|
|
|
|
FSM_IDLE: if (I_STB) fsm <= FSM_TX_HEX;
|
|
|
|
FSM_TX_HEX:
|
|
if (tx_rdy && (char_cnt == 0) && (word_cnt == 0))
|
|
fsm <= FSM_TX_CR;
|
|
else if (tx_rdy && (char_cnt == 0)) fsm <= FSM_TX_SEP;
|
|
else if (tx_rdy && (char_cnt != 0)) fsm <= FSM_TX_HEX;
|
|
|
|
FSM_TX_SEP: if (tx_rdy) fsm <= FSM_TX_HEX;
|
|
FSM_TX_CR: if (tx_rdy) fsm <= FSM_TX_LF;
|
|
FSM_TX_LF: if (tx_rdy) fsm <= FSM_IDLE;
|
|
|
|
endcase
|
|
|
|
// ============================================================================
|
|
// Data to ASCII converter
|
|
reg o_stb;
|
|
reg [7:0] o_dat;
|
|
|
|
always @(posedge CLK or posedge RST)
|
|
if (RST)
|
|
o_stb <= 1'd0;
|
|
else
|
|
o_stb <= tx_req & tx_rdy;
|
|
|
|
always @(posedge CLK)
|
|
if (fsm == FSM_TX_CR)
|
|
o_dat <= 8'h0D;
|
|
else if (fsm == FSM_TX_LF)
|
|
o_dat <= 8'h0A;
|
|
else if (fsm == FSM_TX_SEP)
|
|
o_dat <= "_";
|
|
else if (fsm == FSM_TX_HEX) case (sr_dat)
|
|
4'h0: o_dat <= "0";
|
|
4'h1: o_dat <= "1";
|
|
4'h2: o_dat <= "2";
|
|
4'h3: o_dat <= "3";
|
|
4'h4: o_dat <= "4";
|
|
4'h5: o_dat <= "5";
|
|
4'h6: o_dat <= "6";
|
|
4'h7: o_dat <= "7";
|
|
4'h8: o_dat <= "8";
|
|
4'h9: o_dat <= "9";
|
|
4'hA: o_dat <= "A";
|
|
4'hB: o_dat <= "B";
|
|
4'hC: o_dat <= "C";
|
|
4'hD: o_dat <= "D";
|
|
4'hE: o_dat <= "E";
|
|
4'hF: o_dat <= "F";
|
|
endcase
|
|
|
|
assign O_STB = o_stb;
|
|
assign O_DAT = o_dat;
|
|
|
|
endmodule
|