blob: 54a3cb4e59023ebea30af9b4e0c12362dddb7566 [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
shalanfd13eb52020-08-21 16:48:07 +020020module simpleuart_wb # (
21 parameter BASE_ADR = 32'h 2000_0000,
22 parameter CLK_DIV = 8'h00,
Tim Edwardsca2f3182020-10-06 10:05:11 -040023 parameter DATA = 8'h04,
24 parameter CONFIG = 8'h08
shalanfd13eb52020-08-21 16:48:07 +020025) (
26 input wb_clk_i,
27 input wb_rst_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040028
shalanfd13eb52020-08-21 16:48:07 +020029 input [31:0] wb_adr_i, // (verify): input address was originaly 22 bits , why ? (max number of words ?)
30 input [31:0] wb_dat_i,
31 input [3:0] wb_sel_i,
32 input wb_we_i,
33 input wb_cyc_i,
34 input wb_stb_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040035
shalanfd13eb52020-08-21 16:48:07 +020036 output wb_ack_o,
37 output [31:0] wb_dat_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040038
Tim Edwardsca2f3182020-10-06 10:05:11 -040039 output uart_enabled,
shalanfd13eb52020-08-21 16:48:07 +020040 output ser_tx,
41 input ser_rx
42
Tim Edwardscd64af52020-08-07 11:11:58 -040043);
shalanfd13eb52020-08-21 16:48:07 +020044 wire [31:0] simpleuart_reg_div_do;
45 wire [31:0] simpleuart_reg_dat_do;
Tim Edwardsca2f3182020-10-06 10:05:11 -040046 wire [31:0] simpleuart_reg_cfg_do;
Tim Edwardscd64af52020-08-07 11:11:58 -040047
shalanfd13eb52020-08-21 16:48:07 +020048 wire resetn = ~wb_rst_i;
49 wire valid = wb_stb_i && wb_cyc_i;
50 wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
51 wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
Tim Edwardsca2f3182020-10-06 10:05:11 -040052 wire simpleuart_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG));
Tim Edwardscd64af52020-08-07 11:11:58 -040053
Tim Edwardsca2f3182020-10-06 10:05:11 -040054 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 +020055 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 -040056 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 -040057
shalanfd13eb52020-08-21 16:48:07 +020058 wire [31:0] mem_wdata = wb_dat_i;
59 wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable
Tim Edwardscd64af52020-08-07 11:11:58 -040060
Tim Edwardsca2f3182020-10-06 10:05:11 -040061 assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do:
62 simpleuart_reg_cfg_sel ? simpleuart_reg_cfg_do:
63 simpleuart_reg_dat_do;
64 assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel
65 || simpleuart_reg_cfg_sel) && (!reg_dat_wait);
shalanfd13eb52020-08-21 16:48:07 +020066
67 simpleuart simpleuart (
68 .clk (wb_clk_i),
69 .resetn (resetn),
Tim Edwardscd64af52020-08-07 11:11:58 -040070
shalanfd13eb52020-08-21 16:48:07 +020071 .ser_tx (ser_tx),
72 .ser_rx (ser_rx),
Tim Edwardsca2f3182020-10-06 10:05:11 -040073 .enabled (uart_enabled),
Tim Edwardscd64af52020-08-07 11:11:58 -040074
shalanfd13eb52020-08-21 16:48:07 +020075 .reg_div_we (reg_div_we),
76 .reg_div_di (mem_wdata),
77 .reg_div_do (simpleuart_reg_div_do),
Tim Edwardscd64af52020-08-07 11:11:58 -040078
Tim Edwardsca2f3182020-10-06 10:05:11 -040079 .reg_cfg_we (reg_cfg_we),
80 .reg_cfg_di (mem_wdata),
81 .reg_cfg_do (simpleuart_reg_cfg_do),
82
shalanfd13eb52020-08-21 16:48:07 +020083 .reg_dat_we (reg_dat_we),
84 .reg_dat_re (reg_dat_re),
85 .reg_dat_di (mem_wdata),
86 .reg_dat_do (simpleuart_reg_dat_do),
87 .reg_dat_wait(reg_dat_wait)
88 );
Tim Edwardscd64af52020-08-07 11:11:58 -040089
shalanfd13eb52020-08-21 16:48:07 +020090endmodule
91
92module simpleuart (
93 input clk,
94 input resetn,
95
Tim Edwardsca2f3182020-10-06 10:05:11 -040096 output enabled,
shalanfd13eb52020-08-21 16:48:07 +020097 output ser_tx,
98 input ser_rx,
99
100 input [3:0] reg_div_we,
101 input [31:0] reg_div_di,
102 output [31:0] reg_div_do,
103
Tim Edwardsca2f3182020-10-06 10:05:11 -0400104 input reg_cfg_we,
105 input [31:0] reg_cfg_di,
106 output [31:0] reg_cfg_do,
107
shalanfd13eb52020-08-21 16:48:07 +0200108 input reg_dat_we,
109 input reg_dat_re,
110 input [31:0] reg_dat_di,
111 output [31:0] reg_dat_do,
112 output reg_dat_wait
113);
114 reg [31:0] cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400115 reg enabled;
shalanfd13eb52020-08-21 16:48:07 +0200116
117 reg [3:0] recv_state;
118 reg [31:0] recv_divcnt;
119 reg [7:0] recv_pattern;
120 reg [7:0] recv_buf_data;
121 reg recv_buf_valid;
122
123 reg [9:0] send_pattern;
124 reg [3:0] send_bitcnt;
125 reg [31:0] send_divcnt;
126 reg send_dummy;
127
128 assign reg_div_do = cfg_divider;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400129 assign reg_ena_do = {31'd0, enabled};
shalanfd13eb52020-08-21 16:48:07 +0200130
131 assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
132 assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
133
134 always @(posedge clk) begin
135 if (!resetn) begin
136 cfg_divider <= 1;
Tim Edwardsca2f3182020-10-06 10:05:11 -0400137 enabled <= 1'b0;
shalanfd13eb52020-08-21 16:48:07 +0200138 end else begin
139 if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
140 if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
141 if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
142 if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
Tim Edwardsca2f3182020-10-06 10:05:11 -0400143 if (reg_cfg_we) enabled <= reg_div_di[0];
shalanfd13eb52020-08-21 16:48:07 +0200144 end
145 end
146
147 always @(posedge clk) begin
148 if (!resetn) begin
149 recv_state <= 0;
150 recv_divcnt <= 0;
151 recv_pattern <= 0;
152 recv_buf_data <= 0;
153 recv_buf_valid <= 0;
154 end else begin
155 recv_divcnt <= recv_divcnt + 1;
156 if (reg_dat_re)
157 recv_buf_valid <= 0;
158 case (recv_state)
159 0: begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400160 if (!ser_rx && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200161 recv_state <= 1;
162 recv_divcnt <= 0;
163 end
164 1: begin
165 if (2*recv_divcnt > cfg_divider) begin
166 recv_state <= 2;
167 recv_divcnt <= 0;
168 end
169 end
170 10: begin
171 if (recv_divcnt > cfg_divider) begin
172 recv_buf_data <= recv_pattern;
173 recv_buf_valid <= 1;
174 recv_state <= 0;
175 end
176 end
177 default: begin
178 if (recv_divcnt > cfg_divider) begin
179 recv_pattern <= {ser_rx, recv_pattern[7:1]};
180 recv_state <= recv_state + 1;
181 recv_divcnt <= 0;
182 end
183 end
184 endcase
185 end
186 end
187
188 assign ser_tx = send_pattern[0];
189
190 always @(posedge clk) begin
Tim Edwardsca2f3182020-10-06 10:05:11 -0400191 if (reg_div_we && enabled)
shalanfd13eb52020-08-21 16:48:07 +0200192 send_dummy <= 1;
193 send_divcnt <= send_divcnt + 1;
194 if (!resetn) begin
195 send_pattern <= ~0;
196 send_bitcnt <= 0;
197 send_divcnt <= 0;
198 send_dummy <= 1;
199 end else begin
200 if (send_dummy && !send_bitcnt) begin
201 send_pattern <= ~0;
202 send_bitcnt <= 15;
203 send_divcnt <= 0;
204 send_dummy <= 0;
205 end else
206 if (reg_dat_we && !send_bitcnt) begin
207 send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
208 send_bitcnt <= 10;
209 send_divcnt <= 0;
210 end else
211 if (send_divcnt > cfg_divider && send_bitcnt) begin
212 send_pattern <= {1'b1, send_pattern[9:1]};
213 send_bitcnt <= send_bitcnt - 1;
214 send_divcnt <= 0;
215 end
216 end
217 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400218endmodule