blob: 51e95c787ee18c8d35222889f3d746129d980652 [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,
23 parameter DATA = 8'h04
24) (
25 input wb_clk_i,
26 input wb_rst_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040027
shalanfd13eb52020-08-21 16:48:07 +020028 input [31:0] wb_adr_i, // (verify): input address was originaly 22 bits , why ? (max number of words ?)
29 input [31:0] wb_dat_i,
30 input [3:0] wb_sel_i,
31 input wb_we_i,
32 input wb_cyc_i,
33 input wb_stb_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040034
shalanfd13eb52020-08-21 16:48:07 +020035 output wb_ack_o,
36 output [31:0] wb_dat_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040037
shalanfd13eb52020-08-21 16:48:07 +020038 output ser_tx,
39 input ser_rx
40
Tim Edwardscd64af52020-08-07 11:11:58 -040041);
shalanfd13eb52020-08-21 16:48:07 +020042 wire [31:0] simpleuart_reg_div_do;
43 wire [31:0] simpleuart_reg_dat_do;
Tim Edwardscd64af52020-08-07 11:11:58 -040044
shalanfd13eb52020-08-21 16:48:07 +020045 wire resetn = ~wb_rst_i;
46 wire valid = wb_stb_i && wb_cyc_i;
47 wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV));
48 wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA));
Tim Edwardscd64af52020-08-07 11:11:58 -040049
shalanfd13eb52020-08-21 16:48:07 +020050 wire [3:0] reg_div_we = simpleuart_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000; // simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000), // sel: depends on address buss
51 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 Edwardscd64af52020-08-07 11:11:58 -040052
shalanfd13eb52020-08-21 16:48:07 +020053 wire [31:0] mem_wdata = wb_dat_i;
54 wire reg_dat_re = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable
Tim Edwardscd64af52020-08-07 11:11:58 -040055
shalanfd13eb52020-08-21 16:48:07 +020056 assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do: simpleuart_reg_dat_do;
57 assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel) && (!reg_dat_wait);
58
59 simpleuart simpleuart (
60 .clk (wb_clk_i),
61 .resetn (resetn),
Tim Edwardscd64af52020-08-07 11:11:58 -040062
shalanfd13eb52020-08-21 16:48:07 +020063 .ser_tx (ser_tx),
64 .ser_rx (ser_rx),
Tim Edwardscd64af52020-08-07 11:11:58 -040065
shalanfd13eb52020-08-21 16:48:07 +020066 .reg_div_we (reg_div_we),
67 .reg_div_di (mem_wdata),
68 .reg_div_do (simpleuart_reg_div_do),
Tim Edwardscd64af52020-08-07 11:11:58 -040069
shalanfd13eb52020-08-21 16:48:07 +020070 .reg_dat_we (reg_dat_we),
71 .reg_dat_re (reg_dat_re),
72 .reg_dat_di (mem_wdata),
73 .reg_dat_do (simpleuart_reg_dat_do),
74 .reg_dat_wait(reg_dat_wait)
75 );
Tim Edwardscd64af52020-08-07 11:11:58 -040076
shalanfd13eb52020-08-21 16:48:07 +020077endmodule
78
79module simpleuart (
80 input clk,
81 input resetn,
82
83 output ser_tx,
84 input ser_rx,
85
86 input [3:0] reg_div_we,
87 input [31:0] reg_div_di,
88 output [31:0] reg_div_do,
89
90 input reg_dat_we,
91 input reg_dat_re,
92 input [31:0] reg_dat_di,
93 output [31:0] reg_dat_do,
94 output reg_dat_wait
95);
96 reg [31:0] cfg_divider;
97
98 reg [3:0] recv_state;
99 reg [31:0] recv_divcnt;
100 reg [7:0] recv_pattern;
101 reg [7:0] recv_buf_data;
102 reg recv_buf_valid;
103
104 reg [9:0] send_pattern;
105 reg [3:0] send_bitcnt;
106 reg [31:0] send_divcnt;
107 reg send_dummy;
108
109 assign reg_div_do = cfg_divider;
110
111 assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
112 assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
113
114 always @(posedge clk) begin
115 if (!resetn) begin
116 cfg_divider <= 1;
117 end else begin
118 if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
119 if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
120 if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
121 if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
122 end
123 end
124
125 always @(posedge clk) begin
126 if (!resetn) begin
127 recv_state <= 0;
128 recv_divcnt <= 0;
129 recv_pattern <= 0;
130 recv_buf_data <= 0;
131 recv_buf_valid <= 0;
132 end else begin
133 recv_divcnt <= recv_divcnt + 1;
134 if (reg_dat_re)
135 recv_buf_valid <= 0;
136 case (recv_state)
137 0: begin
138 if (!ser_rx)
139 recv_state <= 1;
140 recv_divcnt <= 0;
141 end
142 1: begin
143 if (2*recv_divcnt > cfg_divider) begin
144 recv_state <= 2;
145 recv_divcnt <= 0;
146 end
147 end
148 10: begin
149 if (recv_divcnt > cfg_divider) begin
150 recv_buf_data <= recv_pattern;
151 recv_buf_valid <= 1;
152 recv_state <= 0;
153 end
154 end
155 default: begin
156 if (recv_divcnt > cfg_divider) begin
157 recv_pattern <= {ser_rx, recv_pattern[7:1]};
158 recv_state <= recv_state + 1;
159 recv_divcnt <= 0;
160 end
161 end
162 endcase
163 end
164 end
165
166 assign ser_tx = send_pattern[0];
167
168 always @(posedge clk) begin
169 if (reg_div_we)
170 send_dummy <= 1;
171 send_divcnt <= send_divcnt + 1;
172 if (!resetn) begin
173 send_pattern <= ~0;
174 send_bitcnt <= 0;
175 send_divcnt <= 0;
176 send_dummy <= 1;
177 end else begin
178 if (send_dummy && !send_bitcnt) begin
179 send_pattern <= ~0;
180 send_bitcnt <= 15;
181 send_divcnt <= 0;
182 send_dummy <= 0;
183 end else
184 if (reg_dat_we && !send_bitcnt) begin
185 send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
186 send_bitcnt <= 10;
187 send_divcnt <= 0;
188 end else
189 if (send_divcnt > cfg_divider && send_bitcnt) begin
190 send_pattern <= {1'b1, send_pattern[9:1]};
191 send_bitcnt <= send_bitcnt - 1;
192 send_divcnt <= 0;
193 end
194 end
195 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400196endmodule