blob: 50808cb33b1f084b1313c5a009e3bf68563cd81f [file] [log] [blame]
Tim Edwardscd64af52020-08-07 11:11:58 -04001/*
2 * PicoSoC - A simple example SoC using PicoRV32
3 *
4 * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20module simpleuart (
21 input clk,
22 input resetn,
23
24 output ser_tx,
25 input ser_rx,
26
27 input [3:0] reg_div_we,
28 input [31:0] reg_div_di,
29 output [31:0] reg_div_do,
30
31 input reg_dat_we,
32 input reg_dat_re,
33 input [31:0] reg_dat_di,
34 output [31:0] reg_dat_do,
35 output reg_dat_wait
36);
37 reg [31:0] cfg_divider;
38
39 reg [3:0] recv_state;
40 reg [31:0] recv_divcnt;
41 reg [7:0] recv_pattern;
42 reg [7:0] recv_buf_data;
43 reg recv_buf_valid;
44
45 reg [9:0] send_pattern;
46 reg [3:0] send_bitcnt;
47 reg [31:0] send_divcnt;
48 reg send_dummy;
49
50 assign reg_div_do = cfg_divider;
51
52 assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
53 assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
54
55 always @(posedge clk) begin
56 if (!resetn) begin
57 cfg_divider <= 1;
58 end else begin
59 if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
60 if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
61 if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
62 if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
63 end
64 end
65
66 always @(posedge clk) begin
67 if (!resetn) begin
68 recv_state <= 0;
69 recv_divcnt <= 0;
70 recv_pattern <= 0;
71 recv_buf_data <= 0;
72 recv_buf_valid <= 0;
73 end else begin
74 recv_divcnt <= recv_divcnt + 1;
75 if (reg_dat_re)
76 recv_buf_valid <= 0;
77 case (recv_state)
78 0: begin
79 if (!ser_rx)
80 recv_state <= 1;
81 recv_divcnt <= 0;
82 end
83 1: begin
84 if (2*recv_divcnt > cfg_divider) begin
85 recv_state <= 2;
86 recv_divcnt <= 0;
87 end
88 end
89 10: begin
90 if (recv_divcnt > cfg_divider) begin
91 recv_buf_data <= recv_pattern;
92 recv_buf_valid <= 1;
93 recv_state <= 0;
94 end
95 end
96 default: begin
97 if (recv_divcnt > cfg_divider) begin
98 recv_pattern <= {ser_rx, recv_pattern[7:1]};
99 recv_state <= recv_state + 1;
100 recv_divcnt <= 0;
101 end
102 end
103 endcase
104 end
105 end
106
107 assign ser_tx = send_pattern[0];
108
109 always @(posedge clk) begin
110 if (reg_div_we)
111 send_dummy <= 1;
112 send_divcnt <= send_divcnt + 1;
113 if (!resetn) begin
114 send_pattern <= ~0;
115 send_bitcnt <= 0;
116 send_divcnt <= 0;
117 send_dummy <= 1;
118 end else begin
119 if (send_dummy && !send_bitcnt) begin
120 send_pattern <= ~0;
121 send_bitcnt <= 15;
122 send_divcnt <= 0;
123 send_dummy <= 0;
124 end else
125 if (reg_dat_we && !send_bitcnt) begin
126 send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
127 send_bitcnt <= 10;
128 send_divcnt <= 0;
129 end else
130 if (send_divcnt > cfg_divider && send_bitcnt) begin
131 send_pattern <= {1'b1, send_pattern[9:1]};
132 send_bitcnt <= send_bitcnt - 1;
133 send_divcnt <= 0;
134 end
135 end
136 end
137endmodule