|
@@ -10,29 +10,38 @@
|
|
//
|
|
//
|
|
|
|
|
|
module tty (
|
|
module tty (
|
|
- input rst_n,
|
|
|
|
- input sys_clk,
|
|
|
|
- input tty_clk,
|
|
|
|
|
|
+ input rst_n,
|
|
|
|
+ input sys_clk,
|
|
|
|
+ input tty_clk,
|
|
|
|
|
|
- input [7:0] wdata,
|
|
|
|
- input wstrb,
|
|
|
|
|
|
+ input valid,
|
|
|
|
+ input [3:0] wstrb,
|
|
|
|
+ input [31:0] wdata,
|
|
|
|
+ input [0:0] addr,
|
|
|
|
|
|
- output tty_txd
|
|
|
|
|
|
+ output tty_txd
|
|
);
|
|
);
|
|
|
|
+
|
|
|
|
+ `include "functions.sv" // For ModelSim
|
|
|
|
+
|
|
//
|
|
//
|
|
// Baud rate generator; produces a clock enable synchronous
|
|
// Baud rate generator; produces a clock enable synchronous
|
|
// with tty_clk
|
|
// with tty_clk
|
|
//
|
|
//
|
|
- parameter [15:0] DIVISOR = 16'd2; // == tty_clk/(3*16)
|
|
|
|
|
|
+ parameter [31:0] BAUDRATE = 115200;
|
|
|
|
+ parameter [31:0] TTY_CLK = 48000000;
|
|
|
|
+
|
|
|
|
+ localparam divisor_bits = 16;
|
|
|
|
|
|
- reg [15:0] divisor = DIVISOR;
|
|
|
|
- reg [15:0] clk_div;
|
|
|
|
- reg tty_clk_en; // tty clock tick (clock enable)
|
|
|
|
|
|
+ reg [divisor_bits-1:0] divisor_q = round_div(TTY_CLK, BAUDRATE << 4) - 1;
|
|
|
|
+ wire [divisor_bits-1:0] divisor;
|
|
|
|
+ reg [divisor_bits-1:0] clk_div;
|
|
|
|
+ reg tty_clk_en; // tty clock tick (clock enable)
|
|
|
|
|
|
always @(negedge rst_n or posedge tty_clk)
|
|
always @(negedge rst_n or posedge tty_clk)
|
|
if (~rst_n)
|
|
if (~rst_n)
|
|
begin
|
|
begin
|
|
- clk_div <= 16'h0;
|
|
|
|
|
|
+ clk_div <= 16; // Give enough time for synchronizer
|
|
tty_clk_en <= 1'b0;
|
|
tty_clk_en <= 1'b0;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
@@ -70,16 +79,35 @@ module tty (
|
|
.wrfull ( ),
|
|
.wrfull ( ),
|
|
.wrusedw ( )
|
|
.wrusedw ( )
|
|
);
|
|
);
|
|
-
|
|
|
|
|
|
+
|
|
//
|
|
//
|
|
// CPU -> transmitter data. No wait state is needed nor expected.
|
|
// CPU -> transmitter data. No wait state is needed nor expected.
|
|
//
|
|
//
|
|
- reg old_wstrb;
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ // Data mask (if/when needed)
|
|
|
|
+ wire [31:0] wmask = {{8{wstrb[3]}}, {8{wstrb[2]}},
|
|
|
|
+ {8{wstrb[1]}}, {8{wstrb[0]}}};
|
|
|
|
+
|
|
|
|
+ // Data (FIFO) register; normally addressed as byte
|
|
|
|
+ // Protect against long pulses (edge detect)
|
|
|
|
+ reg old_wstrb;
|
|
|
|
+ always @(posedge sys_clk)
|
|
|
|
+ old_wstrb <= wstrb[0];
|
|
|
|
+
|
|
|
|
+ assign tx_wrreq = rst_n & wstrb[0] & (addr == 0);
|
|
|
|
+
|
|
|
|
+ // Divisor register
|
|
always @(posedge sys_clk)
|
|
always @(posedge sys_clk)
|
|
- old_wstrb <= wstrb;
|
|
|
|
|
|
+ if (wstrb[0] & (addr == 1))
|
|
|
|
+ divisor_q <= wdata[divisor_bits-1:0] & wmask;
|
|
|
|
|
|
- assign tx_wrreq = wstrb & ~old_wstrb; // Protect against long pulses
|
|
|
|
|
|
+ synchronizer #(.width(divisor_bits), .stages(2)) sync_divisor
|
|
|
|
+ (
|
|
|
|
+ .rst_n ( rst_n ),
|
|
|
|
+ .clk ( tty_clk ),
|
|
|
|
+ .d ( divisor_q ),
|
|
|
|
+ .q ( divisor )
|
|
|
|
+ );
|
|
|
|
|
|
//
|
|
//
|
|
// Transmitter
|
|
// Transmitter
|