blob: 62a3ea60c1db6bfa20f220b90dc85d906c4bdd94 [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;
Tim Edwardscd64af52020-08-07 11:11:58 -040048
shalanfd13eb52020-08-21 16:48:07 +020049 wire resetn = ~wb_rst_i;
50 wire valid = wb_stb_i && wb_cyc_i;
51 wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
52 wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
Tim Edwardsca2f3182020-10-06 10:05:11 -040053 wire simpleuart_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
Tim Edwardscd64af52020-08-07 11:11:58 -040054
Tim Edwardsca2f3182020-10-06 10:05:11 -040055 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 +020056 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 -040057 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 -040058
shalanfd13eb52020-08-21 16:48:07 +020059 wire [31:0] mem_wdata = wb_dat_i;
60 wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable
Tim Edwardscd64af52020-08-07 11:11:58 -040061
Tim Edwardsca2f3182020-10-06 10:05:11 -040062 assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do:
63 simpleuart_reg_cfg_sel ? simpleuart_reg_cfg_do:
64 simpleuart_reg_dat_do;
65 assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel
66 || simpleuart_reg_cfg_sel) && (!reg_dat_wait);
shalanfd13eb52020-08-21 16:48:07 +020067
68 simpleuart simpleuart (
69 .clk (wb_clk_i),
70 .resetn (resetn),
Tim Edwardscd64af52020-08-07 11:11:58 -040071
shalanfd13eb52020-08-21 16:48:07 +020072 .ser_tx (ser_tx),
73 .ser_rx (ser_rx),
Tim Edwardsca2f3182020-10-06 10:05:11 -040074 .enabled (uart_enabled),
Tim Edwardscd64af52020-08-07 11:11:58 -040075
shalanfd13eb52020-08-21 16:48:07 +020076 .reg_div_we (reg_div_we),
77 .reg_div_di (mem_wdata),
78 .reg_div_do (simpleuart_reg_div_do),
Tim Edwardscd64af52020-08-07 11:11:58 -040079
Tim Edwardsca2f3182020-10-06 10:05:11 -040080 .reg_cfg_we (reg_cfg_we),
81 .reg_cfg_di (mem_wdata),
82 .reg_cfg_do (simpleuart_reg_cfg_do),
83
shalanfd13eb52020-08-21 16:48:07 +020084 .reg_dat_we (reg_dat_we),
85 .reg_dat_re (reg_dat_re),
86 .reg_dat_di (mem_wdata),
87 .reg_dat_do (simpleuart_reg_dat_do),
88 .reg_dat_wait(reg_dat_wait)
89 );
Tim Edwardscd64af52020-08-07 11:11:58 -040090
shalanfd13eb52020-08-21 16:48:07 +020091endmodule
92
93module simpleuart (
94 input clk,
95 input resetn,
96
Tim Edwardsca2f3182020-10-06 10:05:11 -040097 output enabled,
shalanfd13eb52020-08-21 16:48:07 +020098 output ser_tx,
99 input ser_rx,
100
101 input [3:0] reg_div_we,
102 input [31:0] reg_div_di,
103 output [31:0] reg_div_do,
104
Tim Edwardsca2f3182020-10-06 10:05:11 -0400105 input reg_cfg_we,
106 input [31:0] reg_cfg_di,
107 output [31:0] reg_cfg_do,
108
shalanfd13eb52020-08-21 16:48:07 +0200109 input reg_dat_we,
110 input reg_dat_re,
111 input [31:0] reg_dat_di,
112 output [31:0] reg_dat_do,
113 output reg_dat_wait
114);
115 reg [31:0] cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400116 reg enabled;
shalanfd13eb52020-08-21 16:48:07 +0200117
118 reg [3:0] recv_state;
119 reg [31:0] recv_divcnt;
120 reg [7:0] recv_pattern;
121 reg [7:0] recv_buf_data;
122 reg recv_buf_valid;
123
124 reg [9:0] send_pattern;
125 reg [3:0] send_bitcnt;
126 reg [31:0] send_divcnt;
127 reg send_dummy;
128
129 assign reg_div_do = cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400130 assign reg_ena_do = {31'd0, enabled};
shalanfd13eb52020-08-21 16:48:07 +0200131
132 assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
133 assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
134
135 always @(posedge clk) begin
136 if (!resetn) begin
137 cfg_divider <= 1;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400138 enabled <= 1'b0;
shalanfd13eb52020-08-21 16:48:07 +0200139 end else begin
140 if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
141 if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
142 if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
143 if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
Tim Edwardsca2f3182020-10-06 10:05:11 -0400144 if (reg_cfg_we) enabled <= reg_div_di[0];
shalanfd13eb52020-08-21 16:48:07 +0200145 end
146 end
147
148 always @(posedge clk) begin
149 if (!resetn) begin
150 recv_state <= 0;
151 recv_divcnt <= 0;
152 recv_pattern <= 0;
153 recv_buf_data <= 0;
154 recv_buf_valid <= 0;
155 end else begin
156 recv_divcnt <= recv_divcnt + 1;
157 if (reg_dat_re)
158 recv_buf_valid <= 0;
159 case (recv_state)
160 0: begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400161 if (!ser_rx && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200162 recv_state <= 1;
163 recv_divcnt <= 0;
164 end
165 1: begin
166 if (2*recv_divcnt > cfg_divider) begin
167 recv_state <= 2;
168 recv_divcnt <= 0;
169 end
170 end
171 10: begin
172 if (recv_divcnt > cfg_divider) begin
173 recv_buf_data <= recv_pattern;
174 recv_buf_valid <= 1;
175 recv_state <= 0;
176 end
177 end
178 default: begin
179 if (recv_divcnt > cfg_divider) begin
180 recv_pattern <= {ser_rx, recv_pattern[7:1]};
181 recv_state <= recv_state + 1;
182 recv_divcnt <= 0;
183 end
184 end
185 endcase
186 end
187 end
188
189 assign ser_tx = send_pattern[0];
190
191 always @(posedge clk) begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400192 if (reg_div_we && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200193 send_dummy <= 1;
194 send_divcnt <= send_divcnt + 1;
195 if (!resetn) begin
196 send_pattern <= ~0;
197 send_bitcnt <= 0;
198 send_divcnt <= 0;
199 send_dummy <= 1;
200 end else begin
201 if (send_dummy && !send_bitcnt) begin
202 send_pattern <= ~0;
203 send_bitcnt <= 15;
204 send_divcnt <= 0;
205 send_dummy <= 0;
206 end else
207 if (reg_dat_we && !send_bitcnt) begin
208 send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
209 send_bitcnt <= 10;
210 send_divcnt <= 0;
211 end else
212 if (send_divcnt > cfg_divider && send_bitcnt) begin
213 send_pattern <= {1'b1, send_pattern[9:1]};
214 send_bitcnt <= send_bitcnt - 1;
215 send_divcnt <= 0;
216 end
217 end
218 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400219endmodule