ADD: replace the wbuart32 with simple UART
diff --git a/.gitignore b/.gitignore index 9ccca4b..9619c0f 100644 --- a/.gitignore +++ b/.gitignore
@@ -3,3 +3,6 @@ *.lst *.vcd *.gtkw +*.vvp +*.vcd.hier +
diff --git a/openlane/user_proj_example/.config.tcl.swp b/openlane/user_proj_example/.config.tcl.swp new file mode 100644 index 0000000..e06b751 --- /dev/null +++ b/openlane/user_proj_example/.config.tcl.swp Binary files differ
diff --git a/verilog/dv/wb_uart/wb_uart.c b/verilog/dv/wb_uart/wb_uart.c index 754cdab..29db97b 100644 --- a/verilog/dv/wb_uart/wb_uart.c +++ b/verilog/dv/wb_uart/wb_uart.c
@@ -28,12 +28,17 @@ #define reg_SRAM ((volatile uint32_t *)0x30000000) -#define reg_UART_SETUP (*(volatile uint32_t *)0x30001000) -#define reg_UART_FIFO (*(volatile uint32_t *)0x30001004) -#define reg_UART_RX_DATA (*(volatile uint32_t *)0x30001008) -#define reg_UART_TX_DATA (*(volatile uint32_t *)0x3000100C) +// Register space for wbuart32 +// #define reg_UART_SETUP (*(volatile uint32_t *)0x30001000) +// #define reg_UART_FIFO (*(volatile uint32_t *)0x30001004) +// #define reg_UART_RX_DATA (*(volatile uint32_t *)0x30001008) +// #define reg_UART_TX_DATA (*(volatile uint32_t *)0x3000100C) +// Register space for simpleUART +#define reg_UART_CLKDIV (*(volatile uint32_t *)0x30001000) +#define reg_UART_DATA (*(volatile uint32_t *)0x30001004) +#define reg_UART_CONFIG (*(volatile uint32_t *)0x30001008) void main() { @@ -118,23 +123,35 @@ unsigned rx_status = 0; - reg_UART_SETUP = 434; //115200 for 50MHz clock + //reg_UART_SETUP = 434; //115200 for 50MHz clock + reg_UART_CLKDIV = 434-2; + reg_UART_CONFIG = 1; //dummy write to CFG // todo: get rid of that changing the RTL + + bool error = false; do { - rx_status = 0; + rx_status = 0xFFFFFFFF; /* taps: 16 14 13 11; characteristic polynomial: x^16 + x^14 + x^13 + x^11 + 1 */ bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1; lfsr = (lfsr >> 1) | (bit << 15); ++period; data = lfsr % 256; - reg_UART_TX_DATA = data; - while(rx_status == 0) - rx_status = reg_UART_FIFO & 0x00000001; + reg_UART_DATA = data; + + while(rx_status == 0xFFFFFFFF) + rx_status = reg_UART_DATA; + if(rx_status != data) + { + error = true; + break; + } + } while (period < 10 && lfsr != seed && rx_status == data); - } while (period < 2 && lfsr != seed && reg_UART_RX_DATA == data); - - reg_mprj_datal = 0xAB700000; + if(error) + reg_mprj_datal = 0xAB800000; + else + reg_mprj_datal = 0xAB700000;
diff --git a/verilog/dv/wb_uart/wb_uart.elf b/verilog/dv/wb_uart/wb_uart.elf new file mode 100755 index 0000000..34b70df --- /dev/null +++ b/verilog/dv/wb_uart/wb_uart.elf Binary files differ
diff --git a/verilog/dv/wb_uart/wb_uart_tb.v b/verilog/dv/wb_uart/wb_uart_tb.v index 01ae97b..acdd318 100644 --- a/verilog/dv/wb_uart/wb_uart_tb.v +++ b/verilog/dv/wb_uart/wb_uart_tb.v
@@ -112,7 +112,7 @@ // Repeat cycles of 1000 clock edges as needed to complete testbench repeat (70) begin - repeat (10000) @(posedge clock); + repeat (3000) @(posedge clock); // $display("+1000 cycles"); end $display("%c[1;31m",27);
diff --git a/verilog/includes/includes.rtl.caravel_user_project b/verilog/includes/includes.rtl.caravel_user_project index f473d82..48c2430 100644 --- a/verilog/includes/includes.rtl.caravel_user_project +++ b/verilog/includes/includes.rtl.caravel_user_project
@@ -1,6 +1,7 @@ # Caravel user project includes -v $(USER_PROJECT_VERILOG)/rtl/user_project_wrapper.v -v $(USER_PROJECT_VERILOG)/rtl/user_proj_example.v +-v $(USER_PROJECT_VERILOG)/rtl/simpleUART/simple_uart.v -v $(USER_PROJECT_VERILOG)/rtl/sram/sram_wb_wrapper.sv -v $(USER_PROJECT_VERILOG)/rtl/spi/tiny_spi.v -v $(USER_PROJECT_VERILOG)/rtl/wb_interconnect/wb_interconnect.sv
diff --git a/verilog/rtl/simpleUART/simple_uart.v b/verilog/rtl/simpleUART/simple_uart.v new file mode 100644 index 0000000..51b5fd0 --- /dev/null +++ b/verilog/rtl/simpleUART/simple_uart.v
@@ -0,0 +1,228 @@ +`default_nettype none +/* + * SPDX-FileCopyrightText: 2015 Clifford Wolf + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * SPDX-License-Identifier: ISC + */ + +module simpleuartA_wb( + `ifdef USE_POWER_PINS + input wire vccd1 , // User area 1 1.8V supply + input wire vssd1 , // User area 1 digital ground + `endif + input wb_clk_i, + input wb_rst_i, + + input [1:0] wb_adr_i, + input [31:0] wb_dat_i, + input [3:0] wb_sel_i, + input wb_we_i, + input wb_cyc_i, + input wb_stb_i, + + output wb_ack_o, + output [31:0] wb_dat_o, + + output uart_enabled, + output ser_tx, + input ser_rx + +); + + localparam CLK_DIV = 0; + localparam DATA = 1; + localparam CONFIG = 2; + wire [31:0] simpleuartA_reg_div_do; + wire [31:0] simpleuartA_reg_dat_do; + wire [31:0] simpleuartA_reg_cfg_do; + wire reg_dat_wait; + + wire resetn = ~wb_rst_i; + wire valid = wb_stb_i && wb_cyc_i; + wire simpleuartA_reg_div_sel = valid && (wb_adr_i == CLK_DIV); + wire simpleuartA_reg_dat_sel = valid && (wb_adr_i == DATA); + wire simpleuartA_reg_cfg_sel = valid && (wb_adr_i == CONFIG); + + wire [3:0] reg_div_we = simpleuartA_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000; + wire reg_dat_we = simpleuartA_reg_dat_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0; // simpleuartA_reg_dat_sel ? mem_wstrb[0] : 1'b 0 + wire reg_cfg_we = simpleuartA_reg_cfg_sel ? (wb_sel_i[0] & wb_we_i): 1'b 0; + + wire [31:0] mem_wdata = wb_dat_i; + //wire reg_dat_re = simpleuartA_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable //original + wire reg_dat_re = simpleuartA_reg_dat_sel && ~wb_we_i; // read_enable //original + + assign wb_dat_o = simpleuartA_reg_div_sel ? simpleuartA_reg_div_do: + simpleuartA_reg_cfg_sel ? simpleuartA_reg_cfg_do: + simpleuartA_reg_dat_do; + assign wb_ack_o = (simpleuartA_reg_div_sel || simpleuartA_reg_dat_sel + || simpleuartA_reg_cfg_sel) && (!reg_dat_wait); + + simpleuartA simpleuartA ( + .clk (wb_clk_i), + .resetn (resetn), + + .ser_tx (ser_tx), + .ser_rx (ser_rx), + .enabled (uart_enabled), + + .reg_div_we (reg_div_we), + .reg_div_di (mem_wdata), + .reg_div_do (simpleuartA_reg_div_do), + + .reg_cfg_we (reg_cfg_we), + .reg_cfg_di (mem_wdata), + .reg_cfg_do (simpleuartA_reg_cfg_do), + + .reg_dat_we (reg_dat_we), + .reg_dat_re (reg_dat_re), + .reg_dat_di (mem_wdata), + .reg_dat_do (simpleuartA_reg_dat_do), + .reg_dat_wait(reg_dat_wait) + ); + +endmodule + +module simpleuartA ( + input clk, + input resetn, + + output enabled, + output ser_tx, + input ser_rx, + + input [3:0] reg_div_we, + input [31:0] reg_div_di, + output [31:0] reg_div_do, + + input reg_cfg_we, + input [31:0] reg_cfg_di, + output [31:0] reg_cfg_do, + + input reg_dat_we, + input reg_dat_re, + input [31:0] reg_dat_di, + output [31:0] reg_dat_do, + output reg_dat_wait +); + reg [31:0] cfg_divider; + reg enabled; + + reg [3:0] recv_state; + reg [31:0] recv_divcnt; + reg [7:0] recv_pattern; + reg [7:0] recv_buf_data; + reg recv_buf_valid; + + reg [9:0] send_pattern; + reg [3:0] send_bitcnt; + reg [31:0] send_divcnt; + reg send_dummy; + + assign reg_div_do = cfg_divider; + assign reg_cfg_do = {31'd0, enabled}; + + assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy); + assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0; + + always @(posedge clk) begin + if (!resetn) begin + cfg_divider <= 1; + enabled <= 1'b0; + end else begin + if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0]; + if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8]; + if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16]; + if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24]; + //if (reg_cfg_we) enabled <= reg_div_di[0]; // original one + if (reg_cfg_we) enabled <= reg_cfg_di[0]; + end + end + + always @(posedge clk) begin + if (!resetn) begin + recv_state <= 0; + recv_divcnt <= 0; + recv_pattern <= 0; + recv_buf_data <= 0; + recv_buf_valid <= 0; + end else begin + recv_divcnt <= recv_divcnt + 1; + if (reg_dat_re) + recv_buf_valid <= 0; + case (recv_state) + 0: begin + if (!ser_rx && enabled) + recv_state <= 1; + recv_divcnt <= 0; + end + 1: begin + if (2*recv_divcnt > cfg_divider) begin + recv_state <= 2; + recv_divcnt <= 0; + end + end + 10: begin + if (recv_divcnt > cfg_divider) begin + recv_buf_data <= recv_pattern; + recv_buf_valid <= 1; + recv_state <= 0; + end + end + default: begin + if (recv_divcnt > cfg_divider) begin + recv_pattern <= {ser_rx, recv_pattern[7:1]}; + recv_state <= recv_state + 1; + recv_divcnt <= 0; + end + end + endcase + end + end + + assign ser_tx = send_pattern[0]; + + always @(posedge clk) begin + if (reg_div_we && enabled) + send_dummy <= 1; + send_divcnt <= send_divcnt + 1; + if (!resetn) begin + send_pattern <= ~0; + send_bitcnt <= 0; + send_divcnt <= 0; + send_dummy <= 1; + end else begin + if (send_dummy && !send_bitcnt) begin + send_pattern <= ~0; + send_bitcnt <= 15; + send_divcnt <= 0; + send_dummy <= 0; + end else + if (reg_dat_we && !send_bitcnt) begin + send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0}; + send_bitcnt <= 10; + send_divcnt <= 0; + end else + if (send_divcnt > cfg_divider && send_bitcnt) begin + send_pattern <= {1'b1, send_pattern[9:1]}; + send_bitcnt <= send_bitcnt - 1; + send_divcnt <= 0; + end + end + end +endmodule +`default_nettype wire \ No newline at end of file
diff --git a/verilog/rtl/user_proj_example.v b/verilog/rtl/user_proj_example.v index 952b2cd..7b73223 100644 --- a/verilog/rtl/user_proj_example.v +++ b/verilog/rtl/user_proj_example.v
@@ -109,13 +109,11 @@ wire s1_wb_stb_i; wire [ 8:0] s1_wb_adr_o; wire s1_wb_we_i ; - wire [ WB_WIDTH-1:0] s1_wb_dat_i; - wire [UART_DATA_WD/8-1:0] s1_wb_sel_i; - wire [ WB_WIDTH-1:0] s1_wb_dat_o; + wire [WB_WIDTH-1:0] s1_wb_dat_i; + wire [WB_WIDTH/8-1:0] s1_wb_sel_i; + wire [WB_WIDTH-1:0] s1_wb_dat_o; wire s1_wb_ack_o; - - //--------------------------------------------------------------------- // SPI //--------------------------------------------------------------------- @@ -129,11 +127,6 @@ wire s3_wb_ack_o; - - wire [8:0] concat_s0_addr; - wire [8:0] concat_s1_addr; - - wb_interconnect interconnect ( `ifdef USE_POWER_PINS .vccd1 (vccd1 ), // User area 1 1.8V supply @@ -230,35 +223,31 @@ assign io_oeb = {(`MPRJ_IO_PADS){1'b0}}; + - - wbuart wbuart_inst ( + simpleuartA_wb + simpleuartA_wb_dut ( `ifdef USE_POWER_PINS - .vccd1 (vccd1 ), // User area 1 1.8V supply - .vssd1 (vssd1 ), // User area 1 digital ground + .vccd1 (vccd1 ), // User area 1 1.8V supply + .vssd1 (vssd1 ), // User area 1 digital ground `endif - .i_clk (wb_clk_i ), - .i_reset (wb_rst_i ), - .i_wb_cyc (s1_wb_cyc_i ), - .i_wb_stb (s1_wb_stb_i ), - .i_wb_we (s1_wb_we_i ), - .i_wb_addr (s1_wb_adr_o[1:0]), - .i_wb_data (s1_wb_dat_i ), - .i_wb_sel (s1_wb_sel_i ), - .o_wb_stall ( ), - .o_wb_ack (s1_wb_ack_o ), - .o_wb_data (s1_wb_dat_o ), - .i_uart_rx (io_in[15] ), - .o_uart_tx (io_out[16] ), - .i_cts_n (1'b0 ), - .o_rts_n ( ), - .o_uart_rx_int ( ), - .o_uart_tx_int ( ), - .o_uart_rxfifo_int( ), - .o_uart_txfifo_int( ) + .wb_clk_i (wb_clk_i ), + .wb_rst_i (wb_rst_i ), + .wb_adr_i (s1_wb_adr_o[1:0]), + .wb_dat_i (s1_wb_dat_i ), + .wb_sel_i (s1_wb_sel_i ), + .wb_we_i (s1_wb_we_i ), + .wb_cyc_i (s1_wb_cyc_i ), + .wb_stb_i (s1_wb_stb_i ), + .wb_ack_o (s1_wb_ack_o ), + .wb_dat_o (s1_wb_dat_o ), + .uart_enabled ( ), + .ser_tx (io_out[16] ), + .ser_rx (io_in[15]) ); + tiny_spi #( .BAUD_WIDTH(0), .BAUD_DIV (8),
diff --git a/verilog/rtl/wb_interconnect/wb_interconnect.sv b/verilog/rtl/wb_interconnect/wb_interconnect.sv index ae1cbff..ad0ab15 100644 --- a/verilog/rtl/wb_interconnect/wb_interconnect.sv +++ b/verilog/rtl/wb_interconnect/wb_interconnect.sv
@@ -52,7 +52,7 @@ input wire [31:0] s1_wb_dat_i, input wire s1_wb_ack_i, output wire [31:0] s1_wb_dat_o, - output wire [ 8:0] s1_wb_adr_o, + output wire [8:0] s1_wb_adr_o, output wire [ 3:0] s1_wb_sel_o, output wire s1_wb_we_o , output wire s1_wb_cyc_o, @@ -122,19 +122,19 @@ //assign s0_wb_cyc_o = m0_wb_cyc_reg; //assign s0_wb_stb_o = m0_wb_stb_reg; - assign s0_wb_dat_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_dat_i_reg : 2'b00; - assign s0_wb_adr_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_adr_reg : 2'b00; - assign s0_wb_sel_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_sel_reg : 2'b00; - assign s0_wb_we_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_we_reg : 2'b00; - assign s0_wb_cyc_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_cyc_reg : 2'b00; - assign s0_wb_stb_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_stb_reg : 2'b00; + assign s0_wb_dat_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_dat_i_reg : 32'd00; + assign s0_wb_adr_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_adr_reg : 9'd0; + assign s0_wb_sel_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_sel_reg : 4'd0; + assign s0_wb_we_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_we_reg : 1'b0; + assign s0_wb_cyc_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_cyc_reg : 1'b0; + assign s0_wb_stb_o = (m0_wb_tid_reg == 2'b00) ? m0_wb_stb_reg : 1'b0; - assign s1_wb_dat_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_dat_i_reg : 2'b00; - assign s1_wb_adr_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_adr_reg : 2'b00; - assign s1_wb_sel_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_sel_reg : 2'b00; - assign s1_wb_we_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_we_reg : 2'b00; - assign s1_wb_cyc_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_cyc_reg : 2'b00; - assign s1_wb_stb_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_stb_reg : 2'b00; + assign s1_wb_dat_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_dat_i_reg : 32'd0; + assign s1_wb_adr_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_adr_reg : 9'd0; + assign s1_wb_sel_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_sel_reg : 4'd0; + assign s1_wb_we_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_we_reg : 1'b0; + assign s1_wb_cyc_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_cyc_reg : 1'b0; + assign s1_wb_stb_o = (m0_wb_tid_reg == 2'b01) ? m0_wb_stb_reg : 1'b0; // assign s2_wb_dat_o = (m0_wb_tid_reg == 2'b10) ? m0_wb_dat_i_reg : 2'b00; // assign s2_wb_adr_o = (m0_wb_tid_reg == 2'b10) ? m0_wb_adr_reg : 2'b00; @@ -143,12 +143,12 @@ // assign s2_wb_cyc_o = (m0_wb_tid_reg == 2'b10) ? m0_wb_cyc_reg : 2'b00; // assign s2_wb_stb_o = (m0_wb_tid_reg == 2'b10) ? m0_wb_stb_reg : 2'b00; - assign s3_wb_dat_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_dat_i_reg : 2'b00; - assign s3_wb_adr_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_adr_reg : 2'b00; - assign s3_wb_sel_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_sel_reg : 2'b00; - assign s3_wb_we_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_we_reg : 2'b00; - assign s3_wb_cyc_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_cyc_reg : 2'b00; - assign s3_wb_stb_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_stb_reg : 2'b00; + assign s3_wb_dat_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_dat_i_reg : 32'd0; + assign s3_wb_adr_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_adr_reg : 9'd0; + assign s3_wb_sel_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_sel_reg : 4'd0; + assign s3_wb_we_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_we_reg : 1'b0; + assign s3_wb_cyc_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_cyc_reg : 1'b0; + assign s3_wb_stb_o = (m0_wb_tid_reg == 2'b11) ? m0_wb_stb_reg : 1'b0; assign m0_wb_dat_o = s_bus_rd_wb_dat; assign m0_wb_ack_o = s_bus_rd_wb_ack;