Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

uart: new design using FHDL and bank (TX only, incomplete)

  • Loading branch information...
commit 6664af73d11166b97be77470e9ff76d57dd90452 1 parent bb21f75
@sbourdeauducq sbourdeauducq authored
View
1  build.py
@@ -17,7 +17,6 @@ def add_core_files(d, files):
"lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
"lm32_dcache.v", "lm32_top.v", "lm32_debug.v", "lm32_jtag.v", "jtag_cores.v",
"jtag_tap_spartan6.v"])
-add_core_dir("uart")
os.system("rm -rf build/*")
os.chdir("build")
View
74 milkymist/uart/__init__.py
@@ -1,28 +1,56 @@
+from functools import partial
+
from migen.fhdl.structure import *
-from migen.bus import csr
+from migen.bank.description import *
+from migen.bank import csrgen
class Inst:
- def __init__(self, csr_addr, clk_freq, baud=115200, break_en_default=Constant(0)):
- self.bus = csr.Slave("uart")
- declare_signal(self, "tx")
- declare_signal(self, "rx")
- declare_signal(self, "irq")
- declare_signal(self, "brk")
- self._inst = Instance("uart",
- [("csr_do", self.bus.d_o),
- ("uart_tx", self.tx),
- ("irq", self.irq),
- ("break", self.brk)],
- [("csr_a", self.bus.a_i),
- ("csr_we", self.bus.we_i),
- ("csr_di", self.bus.d_i),
- ("uart_rx", self.rx)],
- [("csr_addr", Constant(csr_addr, BV(5))),
- ("clk_freq", clk_freq),
- ("baud", baud),
- ("break_en_default", break_en_default)],
- "sys_clk",
- "sys_rst")
+ def __init__(self, address, clk_freq, baud=115200):
+ self._rxtx = rxtx = Register("rxtx", BV(8))
+ divisor = Register("divisor")
+ self._f_divisor = Field(divisor, "divisor", 8) # TODO: 16
+ stat = Register("stat") # TODO: autogenerated event manager
+ self._f_thre = Field(stat, "thre", access_bus=READ_ONLY, access_dev=WRITE_ONLY)
+
+ self.bank = csrgen.Bank([rxtx, divisor, stat], address=address)
+ d = partial(declare_signal, self)
+ d("tx", reset=1)
+ d("rx")
+
+ d("_enable16")
+ d("_enable16_counter", BV(16))
+ d("_tx_reg", BV(8))
+ d("_tx_bitcount", BV(4))
+ d("_tx_count16", BV(4))
+ d("_tx_busy")
+ self.divisor = int(clk_freq/baud/16); # TODO
def get_fragment(self):
- return Fragment(instances=[self._inst], pads={self.tx, self.rx})
+ comb = [self._enable16.eq(self._enable16_counter == Constant(0, BV(16)))]
+ sync = [self._enable16_counter.eq(self._enable16_counter - 1),
+ If(self._enable16, self._enable16_counter.eq(self.divisor - 1))] # TODO
+
+ sync += [If(self._rxtx.dev_re,
+ self._tx_reg.eq(self._rxtx.dev_r),
+ self._tx_bitcount.eq(0),
+ self._tx_count16.eq(1),
+ self._tx_busy.eq(1),
+ self.tx.eq(0)
+ ).Elif(self._enable16 & self._tx_busy,
+ self._tx_count16.eq(self._tx_count16 + 1),
+ If(self._tx_count16 == Constant(0, BV(4)),
+ self._tx_bitcount.eq(self._tx_bitcount + 1),
+ If(self._tx_bitcount == 8,
+ self.tx.eq(1)
+ ).Elif(self._tx_bitcount == 9,
+ self.tx.eq(1),
+ self._tx_busy.eq(0)
+ ).Else(
+ self.tx.eq(self._tx_reg[0]),
+ self._tx_reg.eq(Cat(self._tx_reg[1:], 0))
+ )
+ )
+ )]
+
+ comb += [self._f_thre.dev_we.eq(1), self._f_thre.dev_w.eq(~self._tx_busy)]
+ return self.bank.get_fragment() + Fragment(comb, sync, pads={self.tx, self.rx})
View
2  top.py
@@ -21,7 +21,7 @@ def get():
register=True,
offset=1)
uart0 = uart.Inst(0, clk_freq, baud=115200)
- csrcon0 = csr.Interconnect(wishbone2csr0.csr, [uart0.bus])
+ csrcon0 = csr.Interconnect(wishbone2csr0.csr, [uart0.bank.interface])
frag = autofragment.from_local()
vns = convtools.Namespace()
View
142 verilog/uart/uart.v
@@ -1,142 +0,0 @@
-/*
- * Milkymist SoC
- * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
- *
- * 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 #(
- parameter csr_addr = 5'h0,
- parameter clk_freq = 100000000,
- parameter baud = 115200,
- parameter break_en_default = 1'b0
-) (
- input sys_clk,
- input sys_rst,
-
- input [13:0] csr_a,
- input csr_we,
- input [7:0] csr_di,
- output reg [7:0] csr_do,
-
- output irq,
-
- input uart_rx,
- output uart_tx,
-
- output break
-);
-
-reg [15:0] divisor;
-wire [7:0] rx_data;
-wire [7:0] tx_data;
-wire tx_wr;
-
-wire uart_tx_transceiver;
-
-uart_transceiver transceiver(
- .sys_clk(sys_clk),
- .sys_rst(sys_rst),
-
- .uart_rx(uart_rx),
- .uart_tx(uart_tx_transceiver),
-
- .divisor(divisor),
-
- .rx_data(rx_data),
- .rx_done(rx_done),
-
- .tx_data(tx_data),
- .tx_wr(tx_wr),
- .tx_done(tx_done),
-
- .break(break_transceiver)
-);
-
-assign uart_tx = thru_en ? uart_rx : uart_tx_transceiver;
-assign break = break_en & break_transceiver;
-
-/* CSR interface */
-wire csr_selected = csr_a[13:9] == csr_addr;
-
-assign irq = (tx_event & tx_irq_en) | (rx_event & rx_irq_en);
-
-assign tx_data = csr_di;
-assign tx_wr = csr_selected & csr_we & (csr_a[2:0] == 3'b000);
-
-parameter default_divisor = clk_freq/baud/16;
-
-reg thru_en;
-reg break_en;
-reg tx_irq_en;
-reg rx_irq_en;
-reg rx_event;
-reg tx_event;
-reg thre;
-
-always @(posedge sys_clk) begin
- if(sys_rst) begin
- divisor <= default_divisor;
- csr_do <= 32'd0;
- thru_en <= 1'b0;
- break_en <= break_en_default;
- rx_irq_en <= 1'b0;
- tx_irq_en <= 1'b0;
- tx_event <= 1'b0;
- rx_event <= 1'b0;
- thre <= 1'b1;
- end else begin
- csr_do <= 32'd0;
- if(break)
- break_en <= 1'b0;
- if(tx_done) begin
- tx_event <= 1'b1;
- thre <= 1'b1;
- end
- if(tx_wr)
- thre <= 1'b0;
- if(rx_done) begin
- rx_event <= 1'b1;
- end
- if(csr_selected) begin
- case(csr_a[2:0])
- 3'b000: csr_do <= rx_data;
-// TODO 3'b001: csr_do <= divisor;
- 3'b010: csr_do <= {tx_event, rx_event, thre};
- 3'b011: csr_do <= {thru_en, tx_irq_en, rx_irq_en};
- 3'b100: csr_do <= {break_en};
- endcase
- if(csr_we) begin
- case(csr_a[2:0])
- 3'b000:; /* handled by transceiver */
-// TODO 3'b001: divisor <= csr_di[15:0];
- 3'b010: begin
- /* write one to clear */
- if(csr_di[1])
- rx_event <= 1'b0;
- if(csr_di[2])
- tx_event <= 1'b0;
- end
- 3'b011: begin
- rx_irq_en <= csr_di[0];
- tx_irq_en <= csr_di[1];
- thru_en <= csr_di[2];
- end
- 3'b100: break_en <= csr_di[0];
- endcase
- end
- end
- end
-end
-
-endmodule
View
165 verilog/uart/uart_transceiver.v
@@ -1,165 +0,0 @@
-/*
- * Milkymist 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,
-
- output reg break
-);
-
-//-----------------------------------------------------------------
-// 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 uart_rx_r;
-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;
- break <= 1'b0;
- uart_rx_r <= 1'b0;
- end else begin
- rx_done <= 1'b0;
- break <= 1'b0;
-
- if(enable16) begin
- uart_rx_r <= uart_rx2;
- if(~rx_busy) begin // look for start bit
- if(~uart_rx2 & uart_rx_r) 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 else if(rx_reg == 8'h00) // break condition
- break <= 1'b1;
- 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
Please sign in to comment.
Something went wrong with that request. Please try again.