blob: 4fe9f0c1899636d97155ed75a3e0973bf91b66c2 [file] [log] [blame]
Matt Venn08cd6eb2020-11-16 12:01:14 +01001`default_nettype none
Tim Edwardscd64af52020-08-07 11:11:58 -04002/*
3 * PicoSoC - A simple example SoC using PicoRV32
4 *
5 * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
shalanfd13eb52020-08-21 16:48:07 +020021module simpleuart_wb # (
22 parameter BASE_ADR = 32'h 2000_0000,
23 parameter CLK_DIV = 8'h00,
Tim Edwardsca2f3182020-10-06 10:05:11 -040024 parameter DATA = 8'h04,
25 parameter CONFIG = 8'h08
shalanfd13eb52020-08-21 16:48:07 +020026) (
27 input wb_clk_i,
28 input wb_rst_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040029
shalanfd13eb52020-08-21 16:48:07 +020030 input [31:0] wb_adr_i, // (verify): input address was originaly 22 bits , why ? (max number of words ?)
31 input [31:0] wb_dat_i,
32 input [3:0] wb_sel_i,
33 input wb_we_i,
34 input wb_cyc_i,
35 input wb_stb_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040036
shalanfd13eb52020-08-21 16:48:07 +020037 output wb_ack_o,
38 output [31:0] wb_dat_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040039
Tim Edwardsca2f3182020-10-06 10:05:11 -040040 output uart_enabled,
shalanfd13eb52020-08-21 16:48:07 +020041 output ser_tx,
42 input ser_rx
43
Tim Edwardscd64af52020-08-07 11:11:58 -040044);
shalanfd13eb52020-08-21 16:48:07 +020045 wire [31:0] simpleuart_reg_div_do;
46 wire [31:0] simpleuart_reg_dat_do;
Tim Edwardsca2f3182020-10-06 10:05:11 -040047 wire [31:0] simpleuart_reg_cfg_do;
Matt Venn336e0822020-11-16 12:03:29 +010048 wire reg_dat_wait;
Tim Edwardscd64af52020-08-07 11:11:58 -040049
shalanfd13eb52020-08-21 16:48:07 +020050 wire resetn = ~wb_rst_i;
51 wire valid = wb_stb_i && wb_cyc_i;
52 wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
53 wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
Tim Edwardsca2f3182020-10-06 10:05:11 -040054 wire simpleuart_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
Tim Edwardscd64af52020-08-07 11:11:58 -040055
Tim Edwardsca2f3182020-10-06 10:05:11 -040056 wire [3:0] reg_div_we = simpleuart_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000;
shalanfd13eb52020-08-21 16:48:07 +020057 wire reg_dat_we = simpleuart_reg_dat_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0; // simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0
Tim Edwardsca2f3182020-10-06 10:05:11 -040058 wire reg_cfg_we = simpleuart_reg_cfg_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0;
Tim Edwardscd64af52020-08-07 11:11:58 -040059
shalanfd13eb52020-08-21 16:48:07 +020060 wire [31:0] mem_wdata = wb_dat_i;
61 wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable
Tim Edwardscd64af52020-08-07 11:11:58 -040062
Tim Edwardsca2f3182020-10-06 10:05:11 -040063 assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do:
64 simpleuart_reg_cfg_sel ? simpleuart_reg_cfg_do:
65 simpleuart_reg_dat_do;
66 assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel
67 || simpleuart_reg_cfg_sel) && (!reg_dat_wait);
shalanfd13eb52020-08-21 16:48:07 +020068
69 simpleuart simpleuart (
70 .clk (wb_clk_i),
71 .resetn (resetn),
Tim Edwardscd64af52020-08-07 11:11:58 -040072
shalanfd13eb52020-08-21 16:48:07 +020073 .ser_tx (ser_tx),
74 .ser_rx (ser_rx),
Tim Edwardsca2f3182020-10-06 10:05:11 -040075 .enabled (uart_enabled),
Tim Edwardscd64af52020-08-07 11:11:58 -040076
shalanfd13eb52020-08-21 16:48:07 +020077 .reg_div_we (reg_div_we),
78 .reg_div_di (mem_wdata),
79 .reg_div_do (simpleuart_reg_div_do),
Tim Edwardscd64af52020-08-07 11:11:58 -040080
Tim Edwardsca2f3182020-10-06 10:05:11 -040081 .reg_cfg_we (reg_cfg_we),
82 .reg_cfg_di (mem_wdata),
83 .reg_cfg_do (simpleuart_reg_cfg_do),
84
shalanfd13eb52020-08-21 16:48:07 +020085 .reg_dat_we (reg_dat_we),
86 .reg_dat_re (reg_dat_re),
87 .reg_dat_di (mem_wdata),
88 .reg_dat_do (simpleuart_reg_dat_do),
89 .reg_dat_wait(reg_dat_wait)
90 );
Tim Edwardscd64af52020-08-07 11:11:58 -040091
shalanfd13eb52020-08-21 16:48:07 +020092endmodule
93
94module simpleuart (
95 input clk,
96 input resetn,
97
Tim Edwardsca2f3182020-10-06 10:05:11 -040098 output enabled,
shalanfd13eb52020-08-21 16:48:07 +020099 output ser_tx,
100 input ser_rx,
101
102 input [3:0] reg_div_we,
103 input [31:0] reg_div_di,
104 output [31:0] reg_div_do,
105
Tim Edwardsca2f3182020-10-06 10:05:11 -0400106 input reg_cfg_we,
107 input [31:0] reg_cfg_di,
108 output [31:0] reg_cfg_do,
109
shalanfd13eb52020-08-21 16:48:07 +0200110 input reg_dat_we,
111 input reg_dat_re,
112 input [31:0] reg_dat_di,
113 output [31:0] reg_dat_do,
114 output reg_dat_wait
115);
116 reg [31:0] cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400117 reg enabled;
shalanfd13eb52020-08-21 16:48:07 +0200118
119 reg [3:0] recv_state;
120 reg [31:0] recv_divcnt;
121 reg [7:0] recv_pattern;
122 reg [7:0] recv_buf_data;
123 reg recv_buf_valid;
124
125 reg [9:0] send_pattern;
126 reg [3:0] send_bitcnt;
127 reg [31:0] send_divcnt;
128 reg send_dummy;
129
Matt Venn336e0822020-11-16 12:03:29 +0100130 wire reg_ena_do;
131
shalanfd13eb52020-08-21 16:48:07 +0200132 assign reg_div_do = cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400133 assign reg_ena_do = {31'd0, enabled};
shalanfd13eb52020-08-21 16:48:07 +0200134
135 assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
136 assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
137
138 always @(posedge clk) begin
139 if (!resetn) begin
140 cfg_divider <= 1;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400141 enabled <= 1'b0;
shalanfd13eb52020-08-21 16:48:07 +0200142 end else begin
143 if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
144 if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
145 if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
146 if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
Tim Edwardsca2f3182020-10-06 10:05:11 -0400147 if (reg_cfg_we) enabled <= reg_div_di[0];
shalanfd13eb52020-08-21 16:48:07 +0200148 end
149 end
150
151 always @(posedge clk) begin
152 if (!resetn) begin
153 recv_state <= 0;
154 recv_divcnt <= 0;
155 recv_pattern <= 0;
156 recv_buf_data <= 0;
157 recv_buf_valid <= 0;
158 end else begin
159 recv_divcnt <= recv_divcnt + 1;
160 if (reg_dat_re)
161 recv_buf_valid <= 0;
162 case (recv_state)
163 0: begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400164 if (!ser_rx && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200165 recv_state <= 1;
166 recv_divcnt <= 0;
167 end
168 1: begin
169 if (2*recv_divcnt > cfg_divider) begin
170 recv_state <= 2;
171 recv_divcnt <= 0;
172 end
173 end
174 10: begin
175 if (recv_divcnt > cfg_divider) begin
176 recv_buf_data <= recv_pattern;
177 recv_buf_valid <= 1;
178 recv_state <= 0;
179 end
180 end
181 default: begin
182 if (recv_divcnt > cfg_divider) begin
183 recv_pattern <= {ser_rx, recv_pattern[7:1]};
184 recv_state <= recv_state + 1;
185 recv_divcnt <= 0;
186 end
187 end
188 endcase
189 end
190 end
191
192 assign ser_tx = send_pattern[0];
193
194 always @(posedge clk) begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400195 if (reg_div_we && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200196 send_dummy <= 1;
197 send_divcnt <= send_divcnt + 1;
198 if (!resetn) begin
199 send_pattern <= ~0;
200 send_bitcnt <= 0;
201 send_divcnt <= 0;
202 send_dummy <= 1;
203 end else begin
204 if (send_dummy && !send_bitcnt) begin
205 send_pattern <= ~0;
206 send_bitcnt <= 15;
207 send_divcnt <= 0;
208 send_dummy <= 0;
209 end else
210 if (reg_dat_we && !send_bitcnt) begin
211 send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
212 send_bitcnt <= 10;
213 send_divcnt <= 0;
214 end else
215 if (send_divcnt > cfg_divider && send_bitcnt) begin
216 send_pattern <= {1'b1, send_pattern[9:1]};
217 send_bitcnt <= send_bitcnt - 1;
218 send_divcnt <= 0;
219 end
220 end
221 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400222endmodule
Tim Edwards581068f2020-11-19 12:45:25 -0500223`default_nettype wire