// synthesis attribute slice_utilization_ratio of RS232 is 7; module RS232 (CLK_I, RST_I, DAT_I, DAT_O, STB_I, WE_I, SEL_I, ACK_O, TX_EMPTY, TX_FULL, RX_EMPTY, RX_FULL, RX, TX); //parameter CLOCK_DIV = 5207; // 9600 bps @ 50 MHz CLK_I parameter CLOCK_DIV = 434; // 115200 bps @ 50 MHz CLK_I input CLK_I; input RST_I; input [31:0] DAT_I; output [31:0] DAT_O; input STB_I; input WE_I; input [3:0] SEL_I; output ACK_O; output TX_EMPTY, TX_FULL; output RX_EMPTY, RX_FULL; input RX; output TX; reg TX = 1'b1; `define IDLE 4'd0 `define START 4'd1 `define BIT0 4'd2 `define BIT1 4'd3 `define BIT2 4'd4 `define BIT3 4'd5 `define BIT4 4'd6 `define BIT5 4'd7 `define BIT6 4'd8 `define BIT7 4'd9 `define STOP 4'd10 reg [17:0] TX_COUNTER; reg [9:0] TX_BUFFER; reg [3:0] TX_STATE = `IDLE; reg [18:0] RX_COUNTER; reg [6:0] RX_BUFFER; reg [3:0] RX_STATE = `IDLE; wire [7:0] TX_DATA; wire [7:0] RX_DATA; FIFO #( .QUEUE_SIZE(4), // 16 characters .DATA_WIDTH(8) ) TransmitFIFO ( .CLK_I(CLK_I), .RST_I(RST_I), .DAT_I(DAT_I[7:0]), .DAT_O(TX_DATA), .QUEUE_I(ACK_O & WE_I & SEL_I[0]), .DEQUEUE_I(TX_STATE == `IDLE), .FULL_O(TX_FULL), .EMPTY_O(TX_EMPTY) ); FIFO #( .QUEUE_SIZE(4), // 16 characters .DATA_WIDTH(8) ) ReceiveFIFO ( .CLK_I(CLK_I), .RST_I(RST_I), .DAT_I({ RX, RX_BUFFER }), .DAT_O(RX_DATA), .QUEUE_I((RX_STATE == `BIT7) & (RX_COUNTER == 0)), .DEQUEUE_I(ACK_O & ~WE_I & SEL_I[0]), .FULL_O(RX_FULL), .EMPTY_O(RX_EMPTY) ); assign DAT_O = { 22'h000000, TX_FULL, ~RX_EMPTY, RX_DATA }; assign ACK_O = STB_I; always @(posedge CLK_I) begin if (TX_STATE == `IDLE) begin TX <= 1'b1; TX_COUNTER <= (CLOCK_DIV - 1); if (~TX_EMPTY) begin TX_BUFFER <= { 1'b1, 1'b1, TX_DATA, 1'b0 }; TX_STATE <= `START; end end else if (~|TX_COUNTER) begin TX <= TX_BUFFER[0]; TX_BUFFER <= TX_BUFFER >> 1; TX_COUNTER <= (CLOCK_DIV - 1); if (TX_STATE == `STOP) TX_STATE <= `IDLE; else TX_STATE <= TX_STATE + 1; end else TX_COUNTER <= TX_COUNTER - 1; end always @(posedge CLK_I) begin if ((RX_STATE == `IDLE) | RST_I) begin RX_COUNTER <= (CLOCK_DIV / 2); if (RX == 1'b0) RX_STATE <= `START; else RX_STATE <= `IDLE; end else if (RX_COUNTER == 0) begin RX_BUFFER <= { RX, RX_BUFFER[6:1] }; RX_COUNTER <= (CLOCK_DIV - 1); if (RX_STATE == `STOP) RX_STATE <= `IDLE; else RX_STATE <= RX_STATE + 1; end else RX_COUNTER <= RX_COUNTER - 1; end endmodule