Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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

  • Loading branch information...
commit 6664af73d11166b97be77470e9ff76d57dd90452 1 parent bb21f75
Sébastien Bourdeauducq authored December 18, 2011
1  build.py
@@ -17,7 +17,6 @@ def add_core_files(d, files):
17 17
 	"lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
18 18
 	"lm32_dcache.v", "lm32_top.v", "lm32_debug.v", "lm32_jtag.v", "jtag_cores.v",
19 19
 	"jtag_tap_spartan6.v"])
20  
-add_core_dir("uart")
21 20
 
22 21
 os.system("rm -rf build/*")
23 22
 os.chdir("build")
74  milkymist/uart/__init__.py
... ...
@@ -1,28 +1,56 @@
  1
+from functools import partial
  2
+
1 3
 from migen.fhdl.structure import *
2  
-from migen.bus import csr
  4
+from migen.bank.description import *
  5
+from migen.bank import csrgen
3 6
 
4 7
 class Inst:
5  
-	def __init__(self, csr_addr, clk_freq, baud=115200, break_en_default=Constant(0)):
6  
-		self.bus = csr.Slave("uart")
7  
-		declare_signal(self, "tx")
8  
-		declare_signal(self, "rx")
9  
-		declare_signal(self, "irq")
10  
-		declare_signal(self, "brk")
11  
-		self._inst = Instance("uart",
12  
-			[("csr_do", self.bus.d_o),
13  
-			("uart_tx", self.tx),
14  
-			("irq", self.irq),
15  
-			("break", self.brk)],
16  
-			[("csr_a", self.bus.a_i),
17  
-			("csr_we", self.bus.we_i),
18  
-			("csr_di", self.bus.d_i),
19  
-			("uart_rx", self.rx)],
20  
-			[("csr_addr", Constant(csr_addr, BV(5))),
21  
-			("clk_freq", clk_freq),
22  
-			("baud", baud),
23  
-			("break_en_default", break_en_default)],
24  
-			"sys_clk",
25  
-			"sys_rst")
  8
+	def __init__(self, address, clk_freq, baud=115200):
  9
+		self._rxtx = rxtx = Register("rxtx", BV(8))
  10
+		divisor = Register("divisor")
  11
+		self._f_divisor = Field(divisor, "divisor", 8) # TODO: 16
  12
+		stat = Register("stat") # TODO: autogenerated event manager
  13
+		self._f_thre = Field(stat, "thre", access_bus=READ_ONLY, access_dev=WRITE_ONLY)
  14
+		
  15
+		self.bank = csrgen.Bank([rxtx, divisor, stat], address=address)
  16
+		d = partial(declare_signal, self)
  17
+		d("tx", reset=1)
  18
+		d("rx")
  19
+		
  20
+		d("_enable16")
  21
+		d("_enable16_counter", BV(16))
  22
+		d("_tx_reg", BV(8))
  23
+		d("_tx_bitcount", BV(4))
  24
+		d("_tx_count16", BV(4))
  25
+		d("_tx_busy")
  26
+		self.divisor = int(clk_freq/baud/16); # TODO
26 27
 	
27 28
 	def get_fragment(self):
28  
-		return Fragment(instances=[self._inst], pads={self.tx, self.rx})
  29
+		comb = [self._enable16.eq(self._enable16_counter == Constant(0, BV(16)))]
  30
+		sync = [self._enable16_counter.eq(self._enable16_counter - 1),
  31
+			If(self._enable16, self._enable16_counter.eq(self.divisor - 1))] # TODO
  32
+		
  33
+		sync += [If(self._rxtx.dev_re,
  34
+			self._tx_reg.eq(self._rxtx.dev_r),
  35
+			self._tx_bitcount.eq(0),
  36
+			self._tx_count16.eq(1),
  37
+			self._tx_busy.eq(1),
  38
+			self.tx.eq(0)
  39
+		).Elif(self._enable16 & self._tx_busy,
  40
+			self._tx_count16.eq(self._tx_count16 + 1),
  41
+			If(self._tx_count16 == Constant(0, BV(4)),
  42
+				self._tx_bitcount.eq(self._tx_bitcount + 1),
  43
+				If(self._tx_bitcount == 8,
  44
+					self.tx.eq(1)
  45
+				).Elif(self._tx_bitcount == 9,
  46
+					self.tx.eq(1),
  47
+					self._tx_busy.eq(0)
  48
+				).Else(
  49
+					self.tx.eq(self._tx_reg[0]),
  50
+					self._tx_reg.eq(Cat(self._tx_reg[1:], 0))
  51
+				)
  52
+			)
  53
+		)]
  54
+		
  55
+		comb += [self._f_thre.dev_we.eq(1), self._f_thre.dev_w.eq(~self._tx_busy)]
  56
+		return self.bank.get_fragment() + Fragment(comb, sync, pads={self.tx, self.rx})
2  top.py
@@ -21,7 +21,7 @@ def get():
21 21
 		register=True,
22 22
 		offset=1)
23 23
 	uart0 = uart.Inst(0, clk_freq, baud=115200)
24  
-	csrcon0 = csr.Interconnect(wishbone2csr0.csr, [uart0.bus])
  24
+	csrcon0 = csr.Interconnect(wishbone2csr0.csr, [uart0.bank.interface])
25 25
 	
26 26
 	frag = autofragment.from_local()
27 27
 	vns = convtools.Namespace()
142  verilog/uart/uart.v
... ...
@@ -1,142 +0,0 @@
1  
-/*
2  
- * Milkymist SoC
3  
- * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
4  
- *
5  
- * This program is free software: you can redistribute it and/or modify
6  
- * it under the terms of the GNU General Public License as published by
7  
- * the Free Software Foundation, version 3 of the License.
8  
- *
9  
- * This program is distributed in the hope that it will be useful,
10  
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  
- * GNU General Public License for more details.
13  
- *
14  
- * You should have received a copy of the GNU General Public License
15  
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  
- */
17  
-
18  
-module uart #(
19  
-	parameter csr_addr = 5'h0,
20  
-	parameter clk_freq = 100000000,
21  
-	parameter baud = 115200,
22  
-	parameter break_en_default = 1'b0
23  
-) (
24  
-	input sys_clk,
25  
-	input sys_rst,
26  
-	
27  
-	input [13:0] csr_a,
28  
-	input csr_we,
29  
-	input [7:0] csr_di,
30  
-	output reg [7:0] csr_do,
31  
-
32  
-	output irq,
33  
-
34  
-	input uart_rx,
35  
-	output uart_tx,
36  
-
37  
-	output break
38  
-);
39  
-
40  
-reg [15:0] divisor;
41  
-wire [7:0] rx_data;
42  
-wire [7:0] tx_data;
43  
-wire tx_wr;
44  
-
45  
-wire uart_tx_transceiver;
46  
-
47  
-uart_transceiver transceiver(
48  
-	.sys_clk(sys_clk),
49  
-	.sys_rst(sys_rst),
50  
-
51  
-	.uart_rx(uart_rx),
52  
-	.uart_tx(uart_tx_transceiver),
53  
-
54  
-	.divisor(divisor),
55  
-
56  
-	.rx_data(rx_data),
57  
-	.rx_done(rx_done),
58  
-
59  
-	.tx_data(tx_data),
60  
-	.tx_wr(tx_wr),
61  
-	.tx_done(tx_done),
62  
-
63  
-	.break(break_transceiver)
64  
-);
65  
-
66  
-assign uart_tx = thru_en ? uart_rx : uart_tx_transceiver;
67  
-assign break = break_en & break_transceiver;
68  
-
69  
-/* CSR interface */
70  
-wire csr_selected = csr_a[13:9] == csr_addr;
71  
-
72  
-assign irq = (tx_event & tx_irq_en) | (rx_event & rx_irq_en);
73  
-
74  
-assign tx_data = csr_di;
75  
-assign tx_wr = csr_selected & csr_we & (csr_a[2:0] == 3'b000);
76  
-
77  
-parameter default_divisor = clk_freq/baud/16;
78  
-
79  
-reg thru_en;
80  
-reg break_en;
81  
-reg tx_irq_en;
82  
-reg rx_irq_en;
83  
-reg rx_event;
84  
-reg tx_event;
85  
-reg thre;
86  
-
87  
-always @(posedge sys_clk) begin
88  
-	if(sys_rst) begin
89  
-		divisor <= default_divisor;
90  
-		csr_do <= 32'd0;
91  
-		thru_en <= 1'b0;
92  
-		break_en <= break_en_default;
93  
-		rx_irq_en <= 1'b0;
94  
-		tx_irq_en <= 1'b0;
95  
-		tx_event <= 1'b0;
96  
-		rx_event <= 1'b0;
97  
-		thre <= 1'b1;
98  
-	end else begin
99  
-		csr_do <= 32'd0;
100  
-		if(break)
101  
-			break_en <= 1'b0;
102  
-		if(tx_done) begin
103  
-			tx_event <= 1'b1;
104  
-			thre <= 1'b1;
105  
-		end
106  
-		if(tx_wr)
107  
-			thre <= 1'b0;
108  
-		if(rx_done) begin
109  
-			rx_event <= 1'b1;
110  
-		end
111  
-		if(csr_selected) begin
112  
-			case(csr_a[2:0])
113  
-				3'b000: csr_do <= rx_data;
114  
-// TODO				3'b001: csr_do <= divisor;
115  
-				3'b010: csr_do <= {tx_event, rx_event, thre};
116  
-				3'b011: csr_do <= {thru_en, tx_irq_en, rx_irq_en};
117  
-				3'b100: csr_do <= {break_en};
118  
-			endcase
119  
-			if(csr_we) begin
120  
-				case(csr_a[2:0])
121  
-					3'b000:; /* handled by transceiver */
122  
-// TODO					3'b001: divisor <= csr_di[15:0];
123  
-					3'b010: begin
124  
-						/* write one to clear */
125  
-						if(csr_di[1])
126  
-							rx_event <= 1'b0;
127  
-						if(csr_di[2])
128  
-							tx_event <= 1'b0;
129  
-					end
130  
-					3'b011: begin
131  
-						rx_irq_en <= csr_di[0];
132  
-						tx_irq_en <= csr_di[1];
133  
-						thru_en <= csr_di[2];
134  
-					end
135  
-					3'b100: break_en <= csr_di[0];
136  
-				endcase
137  
-			end
138  
-		end
139  
-	end
140  
-end
141  
-
142  
-endmodule
165  verilog/uart/uart_transceiver.v
... ...
@@ -1,165 +0,0 @@
1  
-/*
2  
- * Milkymist SoC
3  
- * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4  
- * Copyright (C) 2007 Das Labor
5  
- *
6  
- * This program is free software: you can redistribute it and/or modify
7  
- * it under the terms of the GNU General Public License as published by
8  
- * the Free Software Foundation, version 3 of the License.
9  
- *
10  
- * This program is distributed in the hope that it will be useful,
11  
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  
- * GNU General Public License for more details.
14  
- *
15  
- * You should have received a copy of the GNU General Public License
16  
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  
- */
18  
-
19  
-module uart_transceiver(
20  
-	input sys_rst,
21  
-	input sys_clk,
22  
-
23  
-	input uart_rx,
24  
-	output reg uart_tx,
25  
-
26  
-	input [15:0] divisor,
27  
-
28  
-	output reg [7:0] rx_data,
29  
-	output reg rx_done,
30  
-
31  
-	input [7:0] tx_data,
32  
-	input tx_wr,
33  
-	output reg tx_done,
34  
-
35  
-	output reg break
36  
-);
37  
-
38  
-//-----------------------------------------------------------------
39  
-// enable16 generator
40  
-//-----------------------------------------------------------------
41  
-reg [15:0] enable16_counter;
42  
-
43  
-wire enable16;
44  
-assign enable16 = (enable16_counter == 16'd0);
45  
-
46  
-always @(posedge sys_clk) begin
47  
-	if(sys_rst)
48  
-		enable16_counter <= divisor - 16'b1;
49  
-	else begin
50  
-		enable16_counter <= enable16_counter - 16'd1;
51  
-		if(enable16)
52  
-			enable16_counter <= divisor - 16'b1;
53  
-	end
54  
-end
55  
-
56  
-//-----------------------------------------------------------------
57  
-// Synchronize uart_rx
58  
-//-----------------------------------------------------------------
59  
-reg uart_rx1;
60  
-reg uart_rx2;
61  
-
62  
-always @(posedge sys_clk) begin
63  
-	uart_rx1 <= uart_rx;
64  
-	uart_rx2 <= uart_rx1;
65  
-end
66  
-
67  
-//-----------------------------------------------------------------
68  
-// UART RX Logic
69  
-//-----------------------------------------------------------------
70  
-reg rx_busy;
71  
-reg uart_rx_r;
72  
-reg [3:0] rx_count16;
73  
-reg [3:0] rx_bitcount;
74  
-reg [7:0] rx_reg;
75  
-
76  
-always @(posedge sys_clk) begin
77  
-	if(sys_rst) begin
78  
-		rx_done <= 1'b0;
79  
-		rx_busy <= 1'b0;
80  
-		rx_count16  <= 4'd0;
81  
-		rx_bitcount <= 4'd0;
82  
-		break <= 1'b0;
83  
-		uart_rx_r <= 1'b0;
84  
-	end else begin
85  
-		rx_done <= 1'b0;
86  
-		break <= 1'b0;
87  
-
88  
-		if(enable16) begin
89  
-			uart_rx_r <= uart_rx2;
90  
-			if(~rx_busy) begin // look for start bit
91  
-				if(~uart_rx2 & uart_rx_r) begin // start bit found
92  
-					rx_busy <= 1'b1;
93  
-					rx_count16 <= 4'd7;
94  
-					rx_bitcount <= 4'd0;
95  
-				end
96  
-			end else begin
97  
-				rx_count16 <= rx_count16 + 4'd1;
98  
-
99  
-				if(rx_count16 == 4'd0) begin // sample
100  
-					rx_bitcount <= rx_bitcount + 4'd1;
101  
-
102  
-					if(rx_bitcount == 4'd0) begin // verify startbit
103  
-						if(uart_rx2)
104  
-							rx_busy <= 1'b0;
105  
-					end else if(rx_bitcount == 4'd9) begin
106  
-						rx_busy <= 1'b0;
107  
-						if(uart_rx2) begin // stop bit ok
108  
-							rx_data <= rx_reg;
109  
-							rx_done <= 1'b1;
110  
-						end else if(rx_reg == 8'h00) // break condition
111  
-							break <= 1'b1;
112  
-					end else
113  
-						rx_reg <= {uart_rx2, rx_reg[7:1]};
114  
-				end
115  
-			end
116  
-		end
117  
-	end
118  
-end
119  
-
120  
-//-----------------------------------------------------------------
121  
-// UART TX Logic
122  
-//-----------------------------------------------------------------
123  
-reg tx_busy;
124  
-reg [3:0] tx_bitcount;
125  
-reg [3:0] tx_count16;
126  
-reg [7:0] tx_reg;
127  
-
128  
-always @(posedge sys_clk) begin
129  
-	if(sys_rst) begin
130  
-		tx_done <= 1'b0;
131  
-		tx_busy <= 1'b0;
132  
-		uart_tx <= 1'b1;
133  
-	end else begin
134  
-		tx_done <= 1'b0;
135  
-		if(tx_wr) begin
136  
-			tx_reg <= tx_data;
137  
-			tx_bitcount <= 4'd0;
138  
-			tx_count16 <= 4'd1;
139  
-			tx_busy <= 1'b1;
140  
-			uart_tx <= 1'b0;
141  
-`ifdef SIMULATION
142  
-			$display("UART: %c", tx_data);
143  
-`endif
144  
-		end else if(enable16 && tx_busy) begin
145  
-			tx_count16  <= tx_count16 + 4'd1;
146  
-
147  
-			if(tx_count16 == 4'd0) begin
148  
-				tx_bitcount <= tx_bitcount + 4'd1;
149  
-				
150  
-				if(tx_bitcount == 4'd8) begin
151  
-					uart_tx <= 1'b1;
152  
-				end else if(tx_bitcount == 4'd9) begin
153  
-					uart_tx <= 1'b1;
154  
-					tx_busy <= 1'b0;
155  
-					tx_done <= 1'b1;
156  
-				end else begin
157  
-					uart_tx <= tx_reg[0];
158  
-					tx_reg <= {1'b0, tx_reg[7:1]};
159  
-				end
160  
-			end
161  
-		end
162  
-	end
163  
-end
164  
-
165  
-endmodule

0 notes on commit 6664af7

Please sign in to comment.
Something went wrong with that request. Please try again.