|
- module uart #(
- parameter clk_freq = 50000000,
- parameter baud = 9600
- ) (
- input sys_clk,
- input sys_rst,
-
- output rx_irq,
- output tx_irq,
-
- input uart_rx,
- output uart_tx
- );
-
- wire [7:0] rx_data;
- reg [7:0] tx_data;
- reg tx_wr;
-
- always @(posedge sys_clk)
- begin
- if (rx_irq)
- begin
- tx_data <= rx_data;
- tx_wr <= 1'b1;
- end
- else
- begin
- tx_wr <= 1'b0;
- end
- end
-
- uart_transceiver transceiver(
- .sys_clk(sys_clk),
- .sys_rst(sys_rst),
-
- .uart_rx(uart_rx),
- .uart_tx(uart_tx),
-
- .divisor(clk_freq/baud/16),
-
- .rx_data(rx_data),
- .rx_done(rx_irq),
-
- .tx_data(tx_data),
- .tx_wr(tx_wr),
- .tx_done(tx_irq)
- );
-
- endmodule
module uart #(
parameter clk_freq = 50000000,
parameter baud = 9600
) (
input sys_clk,
input sys_rst,
output rx_irq,
output tx_irq,
input uart_rx,
output uart_tx
);
wire [7:0] rx_data;
reg [7:0] tx_data;
reg tx_wr;
always @(posedge sys_clk)
begin
if (rx_irq)
begin
tx_data <= rx_data;
tx_wr <= 1'b1;
end
else
begin
tx_wr <= 1'b0;
end
end
uart_transceiver transceiver(
.sys_clk(sys_clk),
.sys_rst(sys_rst),
.uart_rx(uart_rx),
.uart_tx(uart_tx),
.divisor(clk_freq/baud/16),
.rx_data(rx_data),
.rx_done(rx_irq),
.tx_data(tx_data),
.tx_wr(tx_wr),
.tx_done(tx_irq)
);
endmodule
uart_transceiver.v
/*
- * Milkymist VJ SoC
- * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
- * Copyright (C) 2007 Das Labor
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- module uart_transceiver(
- input sys_rst,
- input sys_clk,
-
- input uart_rx,
- output reg uart_tx,
-
- input [15:0] divisor,
-
- output reg [7:0] rx_data,
- output reg rx_done,
-
- input [7:0] tx_data,
- input tx_wr,
- output reg tx_done
- );
-
- //-----------------------------------------------------------------
- // enable16 generator
- //-----------------------------------------------------------------
- reg [15:0] enable16_counter;
-
- wire enable16;
- assign enable16 = (enable16_counter == 16'd0);
-
- always @(posedge sys_clk) begin
- if(sys_rst)
- enable16_counter <= divisor - 16'b1;
- else begin
- enable16_counter <= enable16_counter - 16'd1;
- if(enable16)
- enable16_counter <= divisor - 16'b1;
- end
- end
-
- //-----------------------------------------------------------------
- // Synchronize uart_rx
- //-----------------------------------------------------------------
- reg uart_rx1;
- reg uart_rx2;
-
- always @(posedge sys_clk) begin
- uart_rx1 <= uart_rx;
- uart_rx2 <= uart_rx1;
- end
-
- //-----------------------------------------------------------------
- // UART RX Logic
- //-----------------------------------------------------------------
- reg rx_busy;
- reg [3:0] rx_count16;
- reg [3:0] rx_bitcount;
- reg [7:0] rx_reg;
-
- always @(posedge sys_clk) begin
- if(sys_rst) begin
- rx_done <= 1'b0;
- rx_busy <= 1'b0;
- rx_count16 <= 4'd0;
- rx_bitcount <= 4'd0;
- end else begin
- rx_done <= 1'b0;
-
- if(enable16) begin
- if(~rx_busy) begin // look for start bit
- if(~uart_rx2) begin // start bit found
- rx_busy <= 1'b1;
- rx_count16 <= 4'd7;
- rx_bitcount <= 4'd0;
- end
- end else begin
- rx_count16 <= rx_count16 + 4'd1;
-
- if(rx_count16 == 4'd0) begin // sample
- rx_bitcount <= rx_bitcount + 4'd1;
-
- if(rx_bitcount == 4'd0) begin // verify startbit
- if(uart_rx2)
- rx_busy <= 1'b0;
- end else if(rx_bitcount == 4'd9) begin
- rx_busy <= 1'b0;
- if(uart_rx2) begin // stop bit ok
- rx_data <= rx_reg;
- rx_done <= 1'b1;
- end // ignore RX error
- end else
- rx_reg <= {uart_rx2, rx_reg[7:1]};
- end
- end
- end
- end
- end
-
- //-----------------------------------------------------------------
- // UART TX Logic
- //-----------------------------------------------------------------
- reg tx_busy;
- reg [3:0] tx_bitcount;
- reg [3:0] tx_count16;
- reg [7:0] tx_reg;
-
- always @(posedge sys_clk) begin
- if(sys_rst) begin
- tx_done <= 1'b0;
- tx_busy <= 1'b0;
- uart_tx <= 1'b1;
- end else begin
- tx_done <= 1'b0;
- if(tx_wr) begin
- tx_reg <= tx_data;
- tx_bitcount <= 4'd0;
- tx_count16 <= 4'd1;
- tx_busy <= 1'b1;
- uart_tx <= 1'b0;
- `ifdef SIMULATION
- $display("UART:Â %c", tx_data);
- `endif
- end else if(enable16 && tx_busy) begin
- tx_count16 <= tx_count16 + 4'd1;
-
- if(tx_count16 == 4'd0) begin
- tx_bitcount <= tx_bitcount + 4'd1;
-
- if(tx_bitcount == 4'd8) begin
- uart_tx <= 1'b1;
- end else if(tx_bitcount == 4'd9) begin
- uart_tx <= 1'b1;
- tx_busy <= 1'b0;
- tx_done <= 1'b1;
- end else begin
- uart_tx <= tx_reg[0];
- tx_reg <= {1'b0, tx_reg[7:1]};
- end
- end
- end
- end
- end
-
- endmodule
|
|