123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- module tty (
- input rst_n,
- input clk,
- input valid,
- input [3:0] wstrb,
- input [31:0] wdata,
- input [1:0] addr,
- output reg [31:0] rdata,
- output reg irq,
- output tty_txd
- );
- `include "functions.sv" // For ModelSim
-
-
-
-
-
-
-
-
-
-
-
-
- parameter [31:0] BAUDRATE = 115200;
- parameter [31:0] TTY_CLK = 84000000;
- parameter NCO_BITS = 24;
-
- reg [NCO_BITS-1:0] divisor
- = round_div(BAUDRATE << NCO_BITS, TTY_CLK >> 4) - 1'b1;
- reg [NCO_BITS-1:0] nco_q;
- reg tty_clk_en;
- always @(posedge clk)
- { tty_clk_en, nco_q } <= nco_q + divisor + 1'b1;
-
-
-
- reg tx_rdack;
- wire tx_wrreq;
- wire tx_rdempty;
- wire [7:0] tx_data;
- wire [8:0] tx_usedw;
-
- fifo txfifo (
- .aclr ( ~rst_n ),
- .clock ( clk ),
- .data ( wdata ),
- .rdreq ( tx_rdack ),
- .sclr ( 1'b0 ),
- .wrreq ( tx_wrreq ),
- .empty ( tx_rdempty ),
- .full ( ),
- .q ( tx_data ),
- .usedw ( tx_usedw )
- );
-
-
-
- reg [3:0] tx_phase;
- reg [3:0] tx_bits;
- reg [9:0] tx_sr = ~10'b0;
- assign tty_txd = tx_sr[0];
- always @(negedge rst_n or posedge clk)
- if (~rst_n)
- begin
- tx_phase <= 4'h0;
- tx_bits <= 4'd0;
- tx_sr <= ~10'b0;
- tx_rdack <= 1'b0;
- end
- else
- begin
- tx_rdack <= 1'b0;
- if ( tty_clk_en )
- begin
- tx_phase <= tx_phase + 1'b1;
-
- if (tx_phase == 4'hF)
- begin
- tx_sr[8:0] <= tx_sr[9:1];
- tx_sr[9] <= 1'b1;
-
- if (tx_bits == 4'd0)
- begin
- if ( ~tx_rdempty )
- begin
- tx_sr[9:2] <= tx_data;
- tx_sr[1] <= 1'b0;
-
- tx_bits <= 4'd10;
- tx_rdack <= 1'b1;
- end
- end
- else
- begin
- tx_bits <= tx_bits - 1'b1;
- end
- end
- end
- end
-
-
-
-
-
- reg old_wstrb;
- always @(posedge clk)
- old_wstrb <= wstrb[0];
- assign tx_wrreq = valid & wstrb[0] & ~old_wstrb & (addr == 2'b00);
-
- localparam status_bits = 5;
- wire [status_bits-1:0] status;
- assign status[0] = tx_rdempty & (tx_bits == 4'd0);
- assign status[1] = tx_usedw[8:7] == 2'b00;
- assign status[2] = ~tx_usedw[8];
- assign status[3] = tx_usedw[8];
- assign status[4] = tx_usedw[8:7] == 2'b11;
-
- reg [status_bits-1:0] irq_en;
-
-
-
-
- always @(negedge rst_n or posedge clk)
- if (~rst_n)
- begin
- irq_en <= 5'b0;
- end
- else if (valid & (&wstrb))
- case (addr)
- 2'b01: divisor <= wdata[NCO_BITS-1:0];
- 2'b11: irq_en <= wdata[status_bits-1:0];
- endcase
-
- always @(*)
- begin
- rdata = 32'b0;
- case (addr)
- 2'b01: rdata[NCO_BITS-1:0] = divisor;
- 2'b10: rdata[status_bits-1:0] = status;
- 2'b11: rdata[status_bits-1:0] = irq_en;
- default: rdata = 32'b0;
- endcase
- end
-
- always @(negedge rst_n or posedge clk)
- if (~rst_n)
- irq <= 1'b0;
- else
- irq <= |(status & irq_en);
-
- endmodule
|