This repository has been archived by the owner on May 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bcc9324
commit 462a23a
Showing
9 changed files
with
463 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Generated by CIRCT firtool-1.62.0 | ||
module Buffer( | ||
input clock, | ||
reset, | ||
output io_in_ready, | ||
input io_in_valid, | ||
input [7:0] io_in_bits, | ||
input io_out_ready, | ||
output io_out_valid, | ||
output [7:0] io_out_bits | ||
); | ||
|
||
reg stateReg; | ||
reg [7:0] dataReg; | ||
always @(posedge clock) begin | ||
if (reset) begin | ||
stateReg <= 1'h0; | ||
dataReg <= 8'h0; | ||
end | ||
else begin | ||
if (stateReg) | ||
stateReg <= ~io_out_ready & stateReg; | ||
else | ||
stateReg <= io_in_valid | stateReg; | ||
if (~stateReg & io_in_valid) | ||
dataReg <= io_in_bits; | ||
end | ||
end // always @(posedge) | ||
assign io_in_ready = ~stateReg; | ||
assign io_out_valid = stateReg; | ||
assign io_out_bits = dataReg; | ||
endmodule | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Generated by CIRCT firtool-1.62.0 | ||
module BufferedTx( | ||
input clock, | ||
reset, | ||
output io_txd, | ||
io_channel_ready, | ||
input io_channel_valid, | ||
input [7:0] io_channel_bits | ||
); | ||
|
||
wire _buf_io_out_valid; | ||
wire [7:0] _buf_io_out_bits; | ||
wire _tx_io_channel_ready; | ||
Tx tx ( | ||
.clock (clock), | ||
.reset (reset), | ||
.io_txd (io_txd), | ||
.io_channel_ready (_tx_io_channel_ready), | ||
.io_channel_valid (_buf_io_out_valid), | ||
.io_channel_bits (_buf_io_out_bits) | ||
); | ||
Buffer buf_0 ( | ||
.clock (clock), | ||
.reset (reset), | ||
.io_in_ready (io_channel_ready), | ||
.io_in_valid (io_channel_valid), | ||
.io_in_bits (io_channel_bits), | ||
.io_out_ready (_tx_io_channel_ready), | ||
.io_out_valid (_buf_io_out_valid), | ||
.io_out_bits (_buf_io_out_bits) | ||
); | ||
endmodule | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Generated by CIRCT firtool-1.62.0 | ||
module Sender( | ||
input clock, | ||
reset, | ||
output io_txd | ||
); | ||
|
||
wire _tx_io_channel_ready; | ||
wire [15:0][6:0] _GEN = | ||
'{7'h48, | ||
7'h48, | ||
7'h48, | ||
7'h48, | ||
7'h21, | ||
7'h64, | ||
7'h6C, | ||
7'h72, | ||
7'h6F, | ||
7'h57, | ||
7'h20, | ||
7'h6F, | ||
7'h6C, | ||
7'h6C, | ||
7'h65, | ||
7'h48}; | ||
reg [7:0] cntReg; | ||
wire _tx_io_channel_valid_T = cntReg != 8'hC; | ||
always @(posedge clock) begin | ||
if (reset) | ||
cntReg <= 8'h0; | ||
else if (_tx_io_channel_ready & _tx_io_channel_valid_T) | ||
cntReg <= cntReg + 8'h1; | ||
end // always @(posedge) | ||
BufferedTx tx ( | ||
.clock (clock), | ||
.reset (reset), | ||
.io_txd (io_txd), | ||
.io_channel_ready (_tx_io_channel_ready), | ||
.io_channel_valid (_tx_io_channel_valid_T), | ||
.io_channel_bits ({1'h0, _GEN[cntReg[3:0]]}) | ||
); | ||
endmodule | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Generated by CIRCT firtool-1.62.0 | ||
module Tx( | ||
input clock, | ||
reset, | ||
output io_txd, | ||
io_channel_ready, | ||
input io_channel_valid, | ||
input [7:0] io_channel_bits | ||
); | ||
|
||
reg [10:0] shiftReg; | ||
reg [19:0] cntReg; | ||
reg [3:0] bitsReg; | ||
wire _io_channel_ready_T = cntReg == 20'h0; | ||
always @(posedge clock) begin | ||
if (reset) begin | ||
shiftReg <= 11'h7FF; | ||
cntReg <= 20'h0; | ||
bitsReg <= 4'h0; | ||
end | ||
else if (_io_channel_ready_T) begin | ||
if (|bitsReg) begin | ||
shiftReg <= {1'h1, shiftReg[10:1]}; | ||
bitsReg <= bitsReg - 4'h1; | ||
end | ||
else begin | ||
shiftReg <= io_channel_valid ? {2'h3, io_channel_bits, 1'h0} : 11'h7FF; | ||
if (io_channel_valid) | ||
bitsReg <= 4'hB; | ||
end | ||
cntReg <= 20'h1B1; | ||
end | ||
else | ||
cntReg <= cntReg - 20'h1; | ||
end // always @(posedge) | ||
assign io_txd = shiftReg[0]; | ||
assign io_channel_ready = _io_channel_ready_T & ~(|bitsReg); | ||
endmodule | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Generated by CIRCT firtool-1.62.0 | ||
module UartMain( | ||
input clock, | ||
reset, | ||
io_rxd, | ||
output io_txd | ||
); | ||
|
||
Sender s ( | ||
.clock (clock), | ||
.reset (reset), | ||
.io_txd (io_txd) | ||
); | ||
endmodule | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
/* | ||
* | ||
* A UART is a serial port, also called an RS232 interface. | ||
* | ||
* Author: Martin Schoeberl ([email protected]) | ||
* | ||
*/ | ||
package hwdbg.lib.uart | ||
|
||
import chisel3._ | ||
import circt.stage.ChiselStage | ||
import chisel3.util._ | ||
|
||
class UartIO extends DecoupledIO(UInt(8.W)) | ||
|
||
/** | ||
* Transmit part of the UART. | ||
* A minimal version without any additional buffering. | ||
* Use a ready/valid handshaking. | ||
*/ | ||
class Tx(frequency: Int, baudRate: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val txd = Output(UInt(1.W)) | ||
val channel = Flipped(new UartIO()) | ||
}) | ||
|
||
val BIT_CNT = ((frequency + baudRate / 2) / baudRate - 1).asUInt | ||
|
||
val shiftReg = RegInit(0x7ff.U) | ||
val cntReg = RegInit(0.U(20.W)) | ||
val bitsReg = RegInit(0.U(4.W)) | ||
|
||
io.channel.ready := (cntReg === 0.U) && (bitsReg === 0.U) | ||
io.txd := shiftReg(0) | ||
|
||
when(cntReg === 0.U) { | ||
|
||
cntReg := BIT_CNT | ||
when(bitsReg =/= 0.U) { | ||
val shift = shiftReg >> 1 | ||
shiftReg := Cat(1.U, shift(9, 0)) | ||
bitsReg := bitsReg - 1.U | ||
}.otherwise { | ||
when(io.channel.valid) { | ||
shiftReg := Cat(Cat(3.U, io.channel.bits), 0.U) // two stop bits, data, one start bit | ||
bitsReg := 11.U | ||
}.otherwise { | ||
shiftReg := 0x7ff.U | ||
} | ||
} | ||
|
||
}.otherwise { | ||
cntReg := cntReg - 1.U | ||
} | ||
} | ||
|
||
/** | ||
* Receive part of the UART. | ||
* A minimal version without any additional buffering. | ||
* Use a ready/valid handshaking. | ||
* | ||
* The following code is inspired by Tommy's receive code at: | ||
* https://github.com/tommythorn/yarvi | ||
*/ | ||
class Rx(frequency: Int, baudRate: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val rxd = Input(UInt(1.W)) | ||
val channel = new UartIO() | ||
}) | ||
|
||
val BIT_CNT = ((frequency + baudRate / 2) / baudRate - 1).U | ||
val START_CNT = ((3 * frequency / 2 + baudRate / 2) / baudRate - 1).U | ||
|
||
// Sync in the asynchronous RX data, reset to 1 to not start reading after a reset | ||
val rxReg = RegNext(RegNext(io.rxd, 1.U), 1.U) | ||
|
||
val shiftReg = RegInit(0.U(8.W)) | ||
val cntReg = RegInit(0.U(20.W)) | ||
val bitsReg = RegInit(0.U(4.W)) | ||
val valReg = RegInit(false.B) | ||
|
||
when(cntReg =/= 0.U) { | ||
cntReg := cntReg - 1.U | ||
}.elsewhen(bitsReg =/= 0.U) { | ||
cntReg := BIT_CNT | ||
shiftReg := Cat(rxReg, shiftReg >> 1) | ||
bitsReg := bitsReg - 1.U | ||
// the last shifted in | ||
when(bitsReg === 1.U) { | ||
valReg := true.B | ||
} | ||
}.elsewhen(rxReg === 0.U) { // wait 1.5 bits after falling edge of start | ||
cntReg := START_CNT | ||
bitsReg := 8.U | ||
} | ||
|
||
when(valReg && io.channel.ready) { | ||
valReg := false.B | ||
} | ||
|
||
io.channel.bits := shiftReg | ||
io.channel.valid := valReg | ||
} | ||
|
||
/** | ||
* A single byte buffer with a ready/valid interface | ||
*/ | ||
class Buffer extends Module { | ||
val io = IO(new Bundle { | ||
val in = Flipped(new UartIO()) | ||
val out = new UartIO() | ||
}) | ||
|
||
val empty :: full :: Nil = Enum(2) | ||
val stateReg = RegInit(empty) | ||
val dataReg = RegInit(0.U(8.W)) | ||
|
||
io.in.ready := stateReg === empty | ||
io.out.valid := stateReg === full | ||
|
||
when(stateReg === empty) { | ||
when(io.in.valid) { | ||
dataReg := io.in.bits | ||
stateReg := full | ||
} | ||
}.otherwise { // full | ||
when(io.out.ready) { | ||
stateReg := empty | ||
} | ||
} | ||
io.out.bits := dataReg | ||
} | ||
|
||
/** | ||
* A transmitter with a single buffer. | ||
*/ | ||
class BufferedTx(frequency: Int, baudRate: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val txd = Output(UInt(1.W)) | ||
val channel = Flipped(new UartIO()) | ||
}) | ||
val tx = Module(new Tx(frequency, baudRate)) | ||
val buf = Module(new Buffer()) | ||
|
||
buf.io.in <> io.channel | ||
tx.io.channel <> buf.io.out | ||
io.txd <> tx.io.txd | ||
} | ||
|
||
/** | ||
* Send a string. | ||
*/ | ||
class Sender(frequency: Int, baudRate: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val txd = Output(UInt(1.W)) | ||
}) | ||
|
||
val tx = Module(new BufferedTx(frequency, baudRate)) | ||
|
||
io.txd := tx.io.txd | ||
|
||
val msg = "Hello World!" | ||
val text = VecInit(msg.map(_.U)) | ||
val len = msg.length.U | ||
|
||
val cntReg = RegInit(0.U(8.W)) | ||
|
||
tx.io.channel.bits := text(cntReg) | ||
tx.io.channel.valid := cntReg =/= len | ||
|
||
when(tx.io.channel.ready && cntReg =/= len) { | ||
cntReg := cntReg + 1.U | ||
} | ||
} | ||
|
||
class Echo(frequency: Int, baudRate: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val txd = Output(UInt(1.W)) | ||
val rxd = Input(UInt(1.W)) | ||
}) | ||
// io.txd := RegNext(io.rxd) | ||
val tx = Module(new BufferedTx(frequency, baudRate)) | ||
val rx = Module(new Rx(frequency, baudRate)) | ||
io.txd := tx.io.txd | ||
rx.io.rxd := io.rxd | ||
tx.io.channel <> rx.io.channel | ||
} | ||
|
||
class UartMain(frequency: Int, baudRate: Int) extends Module { | ||
val io = IO(new Bundle { | ||
val rxd = Input(UInt(1.W)) | ||
val txd = Output(UInt(1.W)) | ||
}) | ||
|
||
val doSender = true | ||
|
||
if (doSender) { | ||
val s = Module(new Sender(frequency, baudRate)) | ||
io.txd := s.io.txd | ||
} else { | ||
val e = Module(new Echo(frequency, baudRate)) | ||
e.io.rxd := io.rxd | ||
io.txd := e.io.txd | ||
} | ||
|
||
} | ||
|
||
object Main extends App { | ||
// These lines generate the Verilog output | ||
println( | ||
ChiselStage.emitSystemVerilog( | ||
new UartMain(50000000, 115200), | ||
firtoolOpts = Array( | ||
"-disable-all-randomization", | ||
"-strip-debug-info", | ||
"--split-verilog", // The intention for this argument (and next argument) is to separate generated files. | ||
"-o", | ||
"generated/", | ||
) | ||
) | ||
) | ||
} |
Oops, something went wrong.