blob: 71ed6c67abaa91909b7bb03907f099c910257a76 [file] [log] [blame]
Matt Venn08cd6eb2020-11-16 12:01:14 +01001`default_nettype none
Tim Edwardscd64af52020-08-07 11:11:58 -04002/*
Jeff DiCorpoe084ad62021-01-26 01:50:49 -08003 * SPDX-FileCopyrightText: 2015 Clifford Wolf
Tim Edwardscd64af52020-08-07 11:11:58 -04004 * PicoSoC - A simple example SoC using PicoRV32
5 *
6 * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
Jeff DiCorpoe084ad62021-01-26 01:50:49 -080020 * SPDX-License-Identifier: ISC
Tim Edwardscd64af52020-08-07 11:11:58 -040021 */
22
shalanfd13eb52020-08-21 16:48:07 +020023module simpleuart_wb # (
24 parameter BASE_ADR = 32'h 2000_0000,
25 parameter CLK_DIV = 8'h00,
Tim Edwardsca2f3182020-10-06 10:05:11 -040026 parameter DATA = 8'h04,
27 parameter CONFIG = 8'h08
shalanfd13eb52020-08-21 16:48:07 +020028) (
29 input wb_clk_i,
30 input wb_rst_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040031
shalanfd13eb52020-08-21 16:48:07 +020032 input [31:0] wb_adr_i, // (verify): input address was originaly 22 bits , why ? (max number of words ?)
33 input [31:0] wb_dat_i,
34 input [3:0] wb_sel_i,
35 input wb_we_i,
36 input wb_cyc_i,
37 input wb_stb_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040038
shalanfd13eb52020-08-21 16:48:07 +020039 output wb_ack_o,
40 output [31:0] wb_dat_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040041
Tim Edwardsca2f3182020-10-06 10:05:11 -040042 output uart_enabled,
shalanfd13eb52020-08-21 16:48:07 +020043 output ser_tx,
44 input ser_rx
45
Tim Edwardscd64af52020-08-07 11:11:58 -040046);
shalanfd13eb52020-08-21 16:48:07 +020047 wire [31:0] simpleuart_reg_div_do;
48 wire [31:0] simpleuart_reg_dat_do;
Tim Edwardsca2f3182020-10-06 10:05:11 -040049 wire [31:0] simpleuart_reg_cfg_do;
Matt Venn336e0822020-11-16 12:03:29 +010050 wire reg_dat_wait;
Tim Edwardscd64af52020-08-07 11:11:58 -040051
shalanfd13eb52020-08-21 16:48:07 +020052 wire resetn = ~wb_rst_i;
53 wire valid = wb_stb_i && wb_cyc_i;
54 wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
55 wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
Tim Edwardsca2f3182020-10-06 10:05:11 -040056 wire simpleuart_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
Tim Edwardscd64af52020-08-07 11:11:58 -040057
Tim Edwardsca2f3182020-10-06 10:05:11 -040058 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 +020059 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 -040060 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 -040061
shalanfd13eb52020-08-21 16:48:07 +020062 wire [31:0] mem_wdata = wb_dat_i;
63 wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable
Tim Edwardscd64af52020-08-07 11:11:58 -040064
Tim Edwardsca2f3182020-10-06 10:05:11 -040065 assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do:
66 simpleuart_reg_cfg_sel ? simpleuart_reg_cfg_do:
67 simpleuart_reg_dat_do;
68 assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel
69 || simpleuart_reg_cfg_sel) && (!reg_dat_wait);
shalanfd13eb52020-08-21 16:48:07 +020070
71 simpleuart simpleuart (
72 .clk (wb_clk_i),
73 .resetn (resetn),
Tim Edwardscd64af52020-08-07 11:11:58 -040074
shalanfd13eb52020-08-21 16:48:07 +020075 .ser_tx (ser_tx),
76 .ser_rx (ser_rx),
Tim Edwardsca2f3182020-10-06 10:05:11 -040077 .enabled (uart_enabled),
Tim Edwardscd64af52020-08-07 11:11:58 -040078
shalanfd13eb52020-08-21 16:48:07 +020079 .reg_div_we (reg_div_we),
80 .reg_div_di (mem_wdata),
81 .reg_div_do (simpleuart_reg_div_do),
Tim Edwardscd64af52020-08-07 11:11:58 -040082
Tim Edwardsca2f3182020-10-06 10:05:11 -040083 .reg_cfg_we (reg_cfg_we),
84 .reg_cfg_di (mem_wdata),
85 .reg_cfg_do (simpleuart_reg_cfg_do),
86
shalanfd13eb52020-08-21 16:48:07 +020087 .reg_dat_we (reg_dat_we),
88 .reg_dat_re (reg_dat_re),
89 .reg_dat_di (mem_wdata),
90 .reg_dat_do (simpleuart_reg_dat_do),
91 .reg_dat_wait(reg_dat_wait)
92 );
Tim Edwardscd64af52020-08-07 11:11:58 -040093
shalanfd13eb52020-08-21 16:48:07 +020094endmodule
95
96module simpleuart (
97 input clk,
98 input resetn,
99
Tim Edwardsca2f3182020-10-06 10:05:11 -0400100 output enabled,
shalanfd13eb52020-08-21 16:48:07 +0200101 output ser_tx,
102 input ser_rx,
103
104 input [3:0] reg_div_we,
105 input [31:0] reg_div_di,
106 output [31:0] reg_div_do,
107
Tim Edwardsca2f3182020-10-06 10:05:11 -0400108 input reg_cfg_we,
109 input [31:0] reg_cfg_di,
110 output [31:0] reg_cfg_do,
111
shalanfd13eb52020-08-21 16:48:07 +0200112 input reg_dat_we,
113 input reg_dat_re,
114 input [31:0] reg_dat_di,
115 output [31:0] reg_dat_do,
116 output reg_dat_wait
117);
118 reg [31:0] cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400119 reg enabled;
shalanfd13eb52020-08-21 16:48:07 +0200120
121 reg [3:0] recv_state;
122 reg [31:0] recv_divcnt;
123 reg [7:0] recv_pattern;
124 reg [7:0] recv_buf_data;
125 reg recv_buf_valid;
126
127 reg [9:0] send_pattern;
128 reg [3:0] send_bitcnt;
129 reg [31:0] send_divcnt;
130 reg send_dummy;
131
Matt Venn336e0822020-11-16 12:03:29 +0100132 wire reg_ena_do;
133
shalanfd13eb52020-08-21 16:48:07 +0200134 assign reg_div_do = cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400135 assign reg_ena_do = {31'd0, enabled};
shalanfd13eb52020-08-21 16:48:07 +0200136
137 assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
138 assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
139
140 always @(posedge clk) begin
141 if (!resetn) begin
142 cfg_divider <= 1;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400143 enabled <= 1'b0;
shalanfd13eb52020-08-21 16:48:07 +0200144 end else begin
145 if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
146 if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
147 if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
148 if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
Tim Edwardsca2f3182020-10-06 10:05:11 -0400149 if (reg_cfg_we) enabled <= reg_div_di[0];
shalanfd13eb52020-08-21 16:48:07 +0200150 end
151 end
152
153 always @(posedge clk) begin
154 if (!resetn) begin
155 recv_state <= 0;
156 recv_divcnt <= 0;
157 recv_pattern <= 0;
158 recv_buf_data <= 0;
159 recv_buf_valid <= 0;
160 end else begin
161 recv_divcnt <= recv_divcnt + 1;
162 if (reg_dat_re)
163 recv_buf_valid <= 0;
164 case (recv_state)
165 0: begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400166 if (!ser_rx && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200167 recv_state <= 1;
168 recv_divcnt <= 0;
169 end
170 1: begin
171 if (2*recv_divcnt > cfg_divider) begin
172 recv_state <= 2;
173 recv_divcnt <= 0;
174 end
175 end
176 10: begin
177 if (recv_divcnt > cfg_divider) begin
178 recv_buf_data <= recv_pattern;
179 recv_buf_valid <= 1;
180 recv_state <= 0;
181 end
182 end
183 default: begin
184 if (recv_divcnt > cfg_divider) begin
185 recv_pattern <= {ser_rx, recv_pattern[7:1]};
186 recv_state <= recv_state + 1;
187 recv_divcnt <= 0;
188 end
189 end
190 endcase
191 end
192 end
193
194 assign ser_tx = send_pattern[0];
195
196 always @(posedge clk) begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400197 if (reg_div_we && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200198 send_dummy <= 1;
199 send_divcnt <= send_divcnt + 1;
200 if (!resetn) begin
201 send_pattern <= ~0;
202 send_bitcnt <= 0;
203 send_divcnt <= 0;
204 send_dummy <= 1;
205 end else begin
206 if (send_dummy && !send_bitcnt) begin
207 send_pattern <= ~0;
208 send_bitcnt <= 15;
209 send_divcnt <= 0;
210 send_dummy <= 0;
211 end else
212 if (reg_dat_we && !send_bitcnt) begin
213 send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
214 send_bitcnt <= 10;
215 send_divcnt <= 0;
216 end else
217 if (send_divcnt > cfg_divider && send_bitcnt) begin
218 send_pattern <= {1'b1, send_pattern[9:1]};
219 send_bitcnt <= send_bitcnt - 1;
220 send_divcnt <= 0;
221 end
222 end
223 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400224endmodule
Tim Edwards581068f2020-11-19 12:45:25 -0500225`default_nettype wire