blob: 2aaf26bc83a3df3196c24cc8c8549468bfac14f6 [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Muhammad Hadir Khan
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
package uart
import chisel3._
import chisel3.util.Cat
class UartTx extends Module {
val io = IO(new Bundle {
// coming from CTRL register
val tx_enable = Input(Bool())
val tick_baud_x16 = Input(Bool())
// coming from CTRL register
val parity_en = Input(Bool())
// Indicating data is available from FIFO and ready to write
val wr = Input(Bool())
val wr_parity = Input(Bool())
val wr_data = Input(UInt(8.W))
val idle = Output(Bool())
val tx = Output(UInt(1.W))
})
val baud_div_q = RegInit(0.U(4.W))
val tick_baud_q = RegInit(0.U(1.W))
val bit_cnt_q = RegInit(0.U(4.W))
val bit_cnt_d = Wire(UInt(4.W))
val sreg_q = RegInit("h7ff".U(11.W)) // all 111111s 11 bits.
val sreg_d = Wire(UInt(11.W))
val tx_q = RegInit(1.U(1.W))
val tx_d = Wire(UInt(1.W))
io.tx := tx_q
when(io.tick_baud_x16) {
val temp_wire = Wire(UInt(5.W))
temp_wire := Cat(0.U(1.W), baud_div_q) + 1.U(5.W)
tick_baud_q := temp_wire(4)
baud_div_q := temp_wire(3,0)
} .otherwise {
tick_baud_q := 0.U
}
bit_cnt_q := bit_cnt_d
sreg_q := sreg_d
tx_q := tx_d
when(!io.tx_enable) {
bit_cnt_d := 0.U
sreg_d := "h7ff".U(11.W)
tx_d := 1.U
} .otherwise {
bit_cnt_d := bit_cnt_q
sreg_d := sreg_q
tx_d := tx_q
when(io.wr) {
// data frame setting up
// Stop Bit If parity then wr_parity else Stop bit Data[MSB:LSB] Start Bit
// | | | |
// ⌵️ ⌵️ ⌵️ ⌵️
sreg_d := Cat(1.U(1.W), Mux(io.parity_en, io.wr_parity, 1.U(1.W)), io.wr_data, 0.U(1.W))
bit_cnt_d := Mux(io.parity_en, 11.U(4.W), 10.U(4.W))
} .elsewhen(tick_baud_q.asBool() && (bit_cnt_q =/= 0.U)) {
sreg_d := Cat(1.U(1.W), sreg_q(10,1))
tx_d := sreg_q(0)
bit_cnt_d := bit_cnt_q - 1.U
}
}
io.idle := Mux(io.tx_enable, bit_cnt_q === 0.U, true.B)
}