Various corrections to simplify the user project I/O wiring connections into the management area. Corrected testbenches for hkspi, mem, uart, perf, and gpio.
diff --git a/verilog/dv/caravel/defs.h b/verilog/dv/caravel/defs.h index ac5dfdf..660b103 100644 --- a/verilog/dv/caravel/defs.h +++ b/verilog/dv/caravel/defs.h
@@ -15,6 +15,7 @@ // UART (0x2000_0000) #define reg_uart_clkdiv (*(volatile uint32_t*)0x20000000) #define reg_uart_data (*(volatile uint32_t*)0x20000004) +#define reg_uart_enable (*(volatile uint32_t*)0x20000008) // GPIO (0x2100_0000) #define reg_gpio_data (*(volatile uint32_t*)0x21000000)
diff --git a/verilog/dv/caravel/mgmt_soc/hkspi/Makefile b/verilog/dv/caravel/mgmt_soc/hkspi/Makefile index 31a859c..b3930e2 100644 --- a/verilog/dv/caravel/mgmt_soc/hkspi/Makefile +++ b/verilog/dv/caravel/mgmt_soc/hkspi/Makefile
@@ -1,3 +1,4 @@ +# ---- Test patterns for project striVe ---- FIRMWARE_PATH = ../.. RTL_PATH = ../../../../rtl IP_PATH = ../../../../ip @@ -16,7 +17,7 @@ %.vvp: %_tb.v %.hex iverilog -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS)-I $(IP_PATH) -I $(RTL_PATH) \ $< -o $@ - + %.vcd: %.vvp vvp $< @@ -24,7 +25,9 @@ ${GCC_PATH}/riscv32-unknown-elf-gcc -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< %.hex: %.elf - ${GCC_PATH}/riscv32-unknown-elf-objcopy -O verilog $< /dev/stdout | sed -e '1 s/@10000000/@00000000/; 2,65537 d;' > $@ + ${GCC_PATH}/riscv32-unknown-elf-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ %.bin: %.elf ${GCC_PATH}/riscv32-unknown-elf-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
diff --git a/verilog/dv/caravel/mgmt_soc/hkspi/hkspi.c b/verilog/dv/caravel/mgmt_soc/hkspi/hkspi.c index a415214..03cb7f5 100644 --- a/verilog/dv/caravel/mgmt_soc/hkspi/hkspi.c +++ b/verilog/dv/caravel/mgmt_soc/hkspi/hkspi.c
@@ -19,20 +19,57 @@ void main() { - // Set clock to 64 kbaud - reg_uart_clkdiv = 625; + // This program is just to keep the processor busy while the + // housekeeping SPI is being accessed, to show that the + // processor is interrupted only when the reset is applied + // through the SPI. - // NOTE: Crystal is running in simulation at 5MHz - // Internal clock is 8x crystal, or 40MHz - // Divided by clkdiv is 64 kHz - // So at this crystal rate, use clkdiv = 4167 for 9600 baud. + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output - // This should appear at the output, received by the testbench UART. - print("\n"); - print(" ____ _ ____ ____\n"); - print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n"); - print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n"); - print(" | __/| | (_| (_) |__) | (_) | |___\n"); - print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n"); + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_data = 0xa0000000; + + // Set clock to 64 kbaud and enable the UART + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Test message + print("\n"); + print(" ____ _ ____ ____\n"); + print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n"); + print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n"); + print(" | __/| | (_| (_) |__) | (_) | |___\n"); + print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n"); + + reg_mprj_data = 0xab000000; }
diff --git a/verilog/dv/caravel/mgmt_soc/hkspi/hkspi_tb.v b/verilog/dv/caravel/mgmt_soc/hkspi/hkspi_tb.v index 13677f7..d139182 100644 --- a/verilog/dv/caravel/mgmt_soc/hkspi/hkspi_tb.v +++ b/verilog/dv/caravel/mgmt_soc/hkspi/hkspi_tb.v
@@ -12,7 +12,11 @@ reg clock; reg SDI, CSB, SCK, RSTB; - wire [1:0] gpio; + wire gpio; + wire [15:0] checkbits; + wire [9:0] noconnect; + wire uart_tx; + wire uart_rx; wire flash_csb; wire flash_clk; @@ -119,52 +123,53 @@ RSTB <= 1'b1; #2000; - // First do a normal read from the housekeeping SPI to + // First do a normal read from the housekeeping SPI to // make sure the housekeeping SPI works. - start_csb(); - write_byte(8'h40); // Read stream command - write_byte(8'h03); // Address (register 3 = product ID) + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) read_byte(tbdata); end_csb(); #10; - $display("Read data = 0x%02x (should be 0x05)", tbdata); + $display("Read data = 0x%02x (should be 0x10)", tbdata); // Toggle external reset - start_csb(); - write_byte(8'h80); // Write stream command - write_byte(8'h07); // Address (register 7 = external reset) - write_byte(8'h01); // Data = 0x01 (apply external reset) - end_csb(); + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h07); // Address (register 7 = external reset) + write_byte(8'h01); // Data = 0x01 (apply external reset) + end_csb(); - start_csb(); - write_byte(8'h80); // Write stream command - write_byte(8'h07); // Address (register 7 = external reset) - write_byte(8'h00); // Data = 0x00 (release external reset) - end_csb(); + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h07); // Address (register 7 = external reset) + write_byte(8'h00); // Data = 0x00 (release external reset) + end_csb(); - // Read all registers (0 to 8) - start_csb(); - write_byte(8'h40); // Read stream command - write_byte(8'h00); // Address (register 3 = product ID) + // Read all registers (0 to 18) + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h00); // Address (register 3 = product ID) read_byte(tbdata); + $display("Read register 0 = 0x%02x (should be 0x00)", tbdata); if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end read_byte(tbdata); $display("Read register 1 = 0x%02x (should be 0x04)", tbdata); - if(tbdata !== 8'h14) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + if(tbdata !== 8'h04) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end read_byte(tbdata); $display("Read register 2 = 0x%02x (should be 0x56)", tbdata); if(tbdata !== 8'h56) begin $display("Monitor: Test HK SPI (RTL) Failed, %02x", tbdata); $finish; end read_byte(tbdata); - $display("Read register 3 = 0x%02x (should be 0x05)", tbdata); - if(tbdata !== 8'h05) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + $display("Read register 3 = 0x%02x (should be 0x10)", tbdata); + if(tbdata !== 8'h10) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end read_byte(tbdata); - $display("Read register 4 = 0x%02x (should be 0x07)", tbdata); - if(tbdata !== 8'h07) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + $display("Read register 4 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end read_byte(tbdata); - $display("Read register 5 = 0x%02x (should be 0x01)", tbdata); - if(tbdata !== 8'h01) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + $display("Read register 5 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end read_byte(tbdata); $display("Read register 6 = 0x%02x (should be 0x00)", tbdata); if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end @@ -172,8 +177,38 @@ $display("Read register 7 = 0x%02x (should be 0x00)", tbdata); if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end read_byte(tbdata); - $display("Read register 8 = 0x%02x (should be 0x00)", tbdata); + $display("Read register 8 = 0x%02x (should be 0x01)", tbdata); + if(tbdata !== 8'h01) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 9 = 0x%02x (should be 0x01)", tbdata); + if(tbdata !== 8'h01) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 10 = 0x%02x (should be 0x00)", tbdata); if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 11 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 12 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 13 = 0x%02x (should be 0xff)", tbdata); + if(tbdata !== 8'hff) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 14 = 0x%02x (should be 0xef)", tbdata); + if(tbdata !== 8'hef) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 15 = 0x%02x (should be 0xff)", tbdata); + if(tbdata !== 8'hff) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 16 = 0x%02x (should be 0x03)", tbdata); + if(tbdata !== 8'h03) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 17 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end + read_byte(tbdata); + $display("Read register 18 = 0x%02x (should be 0x04)", tbdata); + if(tbdata !== 8'h04) begin $display("Monitor: Test HK SPI (RTL) Failed"); $finish; end end_csb(); @@ -191,26 +226,27 @@ assign VSS = 1'b0; assign VDD1V8 = 1'b1; + wire hk_sck; + wire hk_csb; + wire hk_sdi; + + assign hk_sck = SCK; + assign hk_csb = CSB; + assign hk_sdi = SDI; + caravel uut ( .vdd3v3 (VDD3V3), .vdd1v8 (VDD1V8), .vss (VSS), .clock (clock), - .SDI (SDI), - .SDO (SDO), - .CSB (CSB), - .SCK (SCK), - .ser_rx (1'b0), - .ser_tx (tbuart_rx), - .irq (1'b0), .gpio (gpio), + .mprj_io ({checkbits, noconnect[9:1], uart_tx, uart_rx, + hk_sck, hk_csb, hk_sdi, SDO, noconnect[0]}), .flash_csb(flash_csb), .flash_clk(flash_clk), .flash_io0(flash_io0), .flash_io1(flash_io1), - .flash_io2(flash_io2), - .flash_io3(flash_io3), - .RSTB (RSTB) + .resetb (RSTB) ); spiflash #( @@ -220,12 +256,12 @@ .clk(flash_clk), .io0(flash_io0), .io1(flash_io1), - .io2(flash_io2), - .io3(flash_io3) + .io2(), // not used + .io3() // not used ); tbuart tbuart ( - .ser_rx(tbuart_rx) + .ser_rx(uart_tx) ); endmodule
diff --git a/verilog/dv/caravel/mgmt_soc/mem/mem.c b/verilog/dv/caravel/mgmt_soc/mem/mem.c index 31d0f75..8f4b542 100644 --- a/verilog/dv/caravel/mgmt_soc/mem/mem.c +++ b/verilog/dv/caravel/mgmt_soc/mem/mem.c
@@ -12,40 +12,65 @@ void main() { - int i; + int i; - /* All GPIO pins are configured to be output */ - reg_gpio_data = 0; - reg_gpio_ena = 0x0000; + /* Upper 16 user area pins are configured to be GPIO output */ - // start test - reg_gpio_data = 0xA040; + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; - // Test Word R/W - for(i=0; i<10; i++) - ints[i] = i*5000 + 10000; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // start test + reg_mprj_data = 0xA0400000; + + // Test Word R/W + for (i=0; i<10; i++) + ints[i] = i*5000 + 10000; - for(i=0; i<10; i++) - if((i*5000+10000) != ints[i]) reg_gpio_data = 0xAB40; - reg_gpio_data = 0xAB41; - - // Test Half Word R/W - reg_gpio_data = 0xA020; - for(i=0; i<10; i++) - shorts[i] = i*500 + 100; - - for(i=0; i<10; i++) - if((i*500+100) != shorts[i]) reg_gpio_data = 0xAB20; - reg_gpio_data = 0xAB21; + for (i=0; i<10; i++) + if ((i*5000+10000) != ints[i]) + reg_mprj_data = 0xAB400000; - // Test byte R/W - reg_gpio_data = 0xA010; - for(i=0; i<10; i++) - bytes[i] = i*5 + 10; + reg_mprj_data = 0xAB410000; - for(i=0; i<10; i++) - if((i*5+10) != bytes[i]) reg_gpio_data = 0xAB10; - reg_gpio_data = 0xAB11; + // Test Half Word R/W + reg_mprj_data = 0xA0200000; + for (i=0; i<10; i++) + shorts[i] = i*500 + 100; + + for(i=0; i<10; i++) + if((i*500+100) != shorts[i]) + reg_mprj_data = 0xAB200000; + reg_mprj_data = 0xAB210000; + + // Test byte R/W + reg_mprj_data = 0xA0100000; + for(i=0; i<10; i++) + bytes[i] = i*5 + 10; + + for(i=0; i<10; i++) + if((i*5+10) != bytes[i]) + reg_mprj_data = 0xAB100000; + + reg_mprj_data = 0xAB110000; }
diff --git a/verilog/dv/caravel/mgmt_soc/mem/mem_tb.v b/verilog/dv/caravel/mgmt_soc/mem/mem_tb.v index 5248cd7..d815b9d 100644 --- a/verilog/dv/caravel/mgmt_soc/mem/mem_tb.v +++ b/verilog/dv/caravel/mgmt_soc/mem/mem_tb.v
@@ -25,17 +25,15 @@ module mem_tb; reg clock; + reg RSTB; - reg SDI, CSB, SCK, RSTB; - - wire [1:0] gpio; + wire gpio; + wire [15:0] checkbits; + wire [15:0] noconnect; wire flash_csb; wire flash_clk; wire flash_io0; wire flash_io1; - wire flash_io2; - wire flash_io3; - wire SDO; // External clock is used by default. Make this artificially fast for the // simulation. Normally this would be a slow clock and the digital PLL @@ -51,9 +49,9 @@ $dumpfile("mem.vcd"); $dumpvars(0, mem_tb); - // Repeat cycles of 1000 XCLK edges as needed to complete testbench + // Repeat cycles of 1000 clock edges as needed to complete testbench repeat (100) begin - repeat (1000) @(posedge XCLK); + repeat (1000) @(posedge clock); //$display("+1000 cycles"); end $display("%c[1;31m",27); @@ -63,52 +61,47 @@ end initial begin - CSB <= 1'b1; - SCK <= 1'b0; - SDI <= 1'b0; RSTB <= 1'b0; - #1000; RSTB <= 1'b1; // Release reset #2000; - CSB <= 1'b0; // Apply CSB to start transmission end - always @(gpio) begin - if(gpio == 16'hA040) begin + always @(checkbits) begin + if(checkbits == 16'hA040) begin $display("Mem Test (word rw) started"); end - else if(gpio == 16'hAB40) begin + else if(checkbits == 16'hAB40) begin $display("%c[1;31m",27); $display("Monitor: Test MEM (RTL) [word rw] failed"); $display("%c[0m",27); $finish; end - else if(gpio == 16'hAB41) begin + else if(checkbits == 16'hAB41) begin $display("Monitor: Test MEM (RTL) [word rw] passed"); end - else if(gpio == 16'hA020) begin + else if(checkbits == 16'hA020) begin $display("Mem Test (short rw) started"); end - else if(gpio == 16'hAB20) begin + else if(checkbits == 16'hAB20) begin $display("%c[1;31m",27); $display("Monitor: Test MEM (RTL) [short rw] failed"); $display("%c[0m",27); $finish; end - else if(gpio == 16'hAB21) begin + else if(checkbits == 16'hAB21) begin $display("Monitor: Test MEM (RTL) [short rw] passed"); end - else if(gpio == 16'hA010) begin + else if(checkbits == 16'hA010) begin $display("Mem Test (byte rw) started"); end - else if(gpio == 16'hAB10) begin + else if(checkbits == 16'hAB10) begin $display("%c[1;31m",27); $display("Monitor: Test MEM (RTL) [byte rw] failed"); $display("%c[0m",27); $finish; end - else if(gpio == 16'hAB11) begin + else if(checkbits == 16'hAB11) begin $display("Monitor: Test MEM (RTL) [byte rw] passed"); $finish; end @@ -128,22 +121,13 @@ .vdd1v8 (VDD1V8), .vss (VSS), .clock (clock), - .xclk (XCLK), - .SDI (SDI), - .SDO (SDO), - .CSB (CSB), - .SCK (SCK), - .ser_rx (1'b0), - .ser_tx (), - .irq (1'b0), .gpio (gpio), + .mprj_io ({checkbits, noconnect}), .flash_csb(flash_csb), .flash_clk(flash_clk), .flash_io0(flash_io0), .flash_io1(flash_io1), - .flash_io2(flash_io2), - .flash_io3(flash_io3), - .RSTB (RSTB) + .resetb (RSTB) ); spiflash #( @@ -153,8 +137,8 @@ .clk(flash_clk), .io0(flash_io0), .io1(flash_io1), - .io2(flash_io2), - .io3(flash_io3) + .io2(), // not used + .io3() // not used ); endmodule
diff --git a/verilog/dv/caravel/mgmt_soc/perf/perf.c b/verilog/dv/caravel/mgmt_soc/perf/perf.c index bd94f5d..b0edcb9 100644 --- a/verilog/dv/caravel/mgmt_soc/perf/perf.c +++ b/verilog/dv/caravel/mgmt_soc/perf/perf.c
@@ -12,22 +12,43 @@ int main() { - int i; + int i; int sum = 0; - /* All GPIO pins are configured to be output */ - reg_gpio_data = 0; - reg_gpio_ena = 0x0000; + /* Upper 16 user area pins are configured to be GPIO output */ - // start test - reg_gpio_data = 0xA000; + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + reg_mprj_data = 0; + + // start test + reg_mprj_data = 0xA0000000; - for(i=0; i<100; i++) - sum+=(sum + i); + for (i=0; i<100; i++) + sum += (sum + i); - reg_gpio_data = 0xAB00; + reg_mprj_data = 0xAB000000; return sum; - }
diff --git a/verilog/dv/caravel/mgmt_soc/perf/perf_tb.v b/verilog/dv/caravel/mgmt_soc/perf/perf_tb.v index 61a044d..985ca3f 100644 --- a/verilog/dv/caravel/mgmt_soc/perf/perf_tb.v +++ b/verilog/dv/caravel/mgmt_soc/perf/perf_tb.v
@@ -23,19 +23,17 @@ `include "caravel.v" `include "spiflash.v" -module striVe_perf_tb; +module perf_tb; reg clock; + reg RSTB; - reg SDI, CSB, SCK, RSTB; - - wire [1:0] gpio; + wire gpio; + wire [15:0] checkbits; + wire [15:0] noconnect; wire flash_csb; wire flash_clk; wire flash_io0; wire flash_io1; - wire flash_io2; - wire flash_io3; - wire SDO; // External clock is used by default. Make this artificially fast for the // simulation. Normally this would be a slow clock and the digital PLL @@ -50,15 +48,15 @@ reg [31:0] kcycles; initial begin - $dumpfile("striVe_perf.vcd"); - $dumpvars(0, striVe_perf_tb); + $dumpfile("perf.vcd"); + $dumpvars(0, perf_tb); kcycles = 0; - // Repeat cycles of 1000 XCLK edges as needed to complete testbench + // Repeat cycles of 1000 clock edges as needed to complete testbench repeat (150) begin - repeat (1000) @(posedge XCLK); + repeat (1000) @(posedge clock); //$display("+1000 cycles"); - kcycles<=kcycles+1; + kcycles <= kcycles + 1; end $display("%c[1;31m",27); $display ("Monitor: Timeout, Test Performance (RTL) Failed"); @@ -67,24 +65,19 @@ end initial begin - CSB <= 1'b1; - SCK <= 1'b0; - SDI <= 1'b0; RSTB <= 1'b0; - #1000; RSTB <= 1'b1; // Release reset #2000; - CSB <= 1'b0; // Apply CSB to start transmission end - always @(gpio) begin + always @(checkbits) begin //#1 $display("GPIO state = %X ", gpio); - if(gpio == 16'hA000) begin + if(checkbits == 16'hA000) begin kcycles = 0; $display("Performance Test started"); end - else if(gpio == 16'hAB00) begin + else if(checkbits == 16'hAB00) begin //$display("Monitor: number of cycles/100 iterations: %d KCycles", kcycles); $display("Monitor: Test Performance (RTL) passed [%0d KCycles]", kcycles); $finish; @@ -104,22 +97,13 @@ .vdd1v8 (VDD1V8), .vss (VSS), .clock (clock), - .xclk (XCLK), - .SDI (SDI), - .SDO (SDO), - .CSB (CSB), - .SCK (SCK), - .ser_rx (1'b0), - .ser_tx ( ), - .irq (1'b0 ), .gpio (gpio), + .mprj_io ({checkbits, noconnect}), .flash_csb(flash_csb), .flash_clk(flash_clk), .flash_io0(flash_io0), .flash_io1(flash_io1), - .flash_io2(flash_io2), - .flash_io3(flash_io3), - .RSTB (RSTB) + .resetb (RSTB) ); spiflash #( @@ -129,8 +113,8 @@ .clk(flash_clk), .io0(flash_io0), .io1(flash_io1), - .io2(flash_io2), - .io3(flash_io3) + .io2(), // not used + .io3() // not used ); endmodule
diff --git a/verilog/dv/caravel/mgmt_soc/uart/uart.c b/verilog/dv/caravel/mgmt_soc/uart/uart.c index bd4b67d..a0b5cc3 100644 --- a/verilog/dv/caravel/mgmt_soc/uart/uart.c +++ b/verilog/dv/caravel/mgmt_soc/uart/uart.c
@@ -5,23 +5,48 @@ void main() { - // Set clock to 64 kbaud - reg_uart_clkdiv = 625; + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output - // NOTE: XCLK is running in simulation at 40MHz - // Divided by clkdiv is 64 kHz - // So at this crystal rate, use clkdiv = 4167 for 9600 baud. + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; - /* Both GPIO pins are configured to be output */ - reg_gpio_data = 0; - reg_gpio_ena = 0x0000; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; - // start test - reg_gpio_data = 0x0001; + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; - // This should appear at the output, received by the testbench UART. + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Set clock to 64 kbaud and enable the UART + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Start test + reg_mprj_data = 0xa0000000; + + // This should appear at the output, received by the testbench UART. print("\n"); - print("Monitor: Test UART (RTL) passed\n\n"); - reg_gpio_data = 0x0002; -} + // print("Monitor: Test UART (RTL) passed\n\n"); + print("X\n\n"); + reg_mprj_data = 0xab000000; +}
diff --git a/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v b/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v index 4f879fe..425ef1e 100644 --- a/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v +++ b/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v
@@ -29,13 +29,17 @@ reg SDI, CSB, SCK, RSTB; - wire [1:0] gpio; + wire gpio; wire flash_csb; wire flash_clk; wire flash_io0; wire flash_io1; wire flash_io2; wire flash_io3; + wire [15:0] checkbits; + wire [13:0] noconnect; + wire uart_tx; + wire uart_rx; wire SDO; always #12.5 clock <= (clock === 1'b0); @@ -67,12 +71,12 @@ CSB <= 1'b0; end - always @(gpio) begin - if(gpio == 16'hA000) begin + always @(checkbits) begin + if(checkbits == 16'hA000) begin $display("UART Test started"); end - else if(gpio == 16'hAB00) begin - #1000; + else if(checkbits == 16'hAB00) begin + #20000; // Allow time for last transmission $finish; end end @@ -90,21 +94,14 @@ .vdd1v8 (VDD1V8), .vss (VSS), .clock (clock), - .SDI (SDI), - .SDO (SDO), - .CSB (CSB), - .SCK (SCK), - .ser_rx (1'b0), - .ser_tx (tbuart_rx), - .irq (1'b0), .gpio (gpio), + .mprj_io ({checkbits, noconnect[13:5], + uart_tx, uart_rx, noconnect[4:0]}), .flash_csb(flash_csb), .flash_clk(flash_clk), .flash_io0(flash_io0), .flash_io1(flash_io1), - .flash_io2(flash_io2), - .flash_io3(flash_io3), - .RSTB (RSTB) + .resetb (RSTB) ); spiflash #( @@ -114,13 +111,13 @@ .clk(flash_clk), .io0(flash_io0), .io1(flash_io1), - .io2(flash_io2), - .io3(flash_io3) + .io2(), // not used + .io3() // not used ); // Testbench UART tbuart tbuart ( - .ser_rx(tbuart_rx) + .ser_rx(uart_tx) ); endmodule
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v index 58dd692..a39fdea 100644 --- a/verilog/rtl/caravel.v +++ b/verilog/rtl/caravel.v
@@ -319,9 +319,11 @@ .mprj_io_loader_clock(mprj_io_loader_clock), .mprj_io_loader_data(mprj_io_loader_data), .mgmt_in_data(mgmt_io_in), - .mgmt_outz_data({mgmt_io_in[(`MPRJ_IO_PADS-1):2], mgmt_io_nc2}), - .mgmt_out_data({mgmt_io_nc1, sdo_out, jtag_out}), - .mgmt_oeb_data({mgmt_io_nc3, sdo_outenb, jtag_outenb}), + .mgmt_out_data({mgmt_io_in[(`MPRJ_IO_PADS-1):2], mgmt_io_nc2}), + .sdo_out(sdo_out), + .sdo_outenb(sdo_outenb), + .jtag_out(jtag_out), + .jtag_outenb(jtag_outenb), // Mega Project Slave ports (WB MI A) .mprj_cyc_o(mprj_cyc_o_core), .mprj_stb_o(mprj_stb_o_core),
diff --git a/verilog/rtl/housekeeping_spi.v b/verilog/rtl/housekeeping_spi.v index 97bd7a1..0a1cce6 100644 --- a/verilog/rtl/housekeeping_spi.v +++ b/verilog/rtl/housekeeping_spi.v
@@ -52,7 +52,6 @@ vdd, vss, `endif RSTB, SCK, SDI, CSB, SDO, sdo_enb, - mgmt_sck, mgmt_sdi, mgmt_csb, mgmt_sdo, pll_dco_ena, pll_div, pll_sel, pll_trim, pll_bypass, irq, reset, trap, mask_rev_in, pass_thru_reset, @@ -75,11 +74,6 @@ output SDO; // to padframe output sdo_enb; // to padframe - input mgmt_sck; // from management SoC - input mgmt_sdi; // from management SoC - input mgmt_csb; // from management SoC - output mgmt_sdo; // to management SoC - output pll_dco_ena; output [4:0] pll_div; output [2:0] pll_sel; @@ -122,21 +116,7 @@ wire pass_thru_mgmt_delay; wire pass_thru_user; // Mode detected by spi_slave wire pass_thru_user_delay; - - // Connect to management SoC SPI master when mgmt_csb is low - - wire loc_sck; - wire loc_csb; - wire loc_sdi; wire loc_sdo; - wire loc_sdoenb; - - assign loc_csb = (mgmt_csb == 1'b0) ? 1'b0 : CSB; - assign loc_sck = (mgmt_csb == 1'b0) ? mgmt_sck : SCK; - assign loc_sdi = (mgmt_csb == 1'b0) ? mgmt_sdi : SDI; - - assign mgmt_sdo = (mgmt_csb == 1'b0) ? loc_sdo : 1'b0; - assign sdo_enb = (mgmt_csb == 1'b0) ? 1'b1 : loc_sdoenb; // Pass-through mode handling @@ -156,11 +136,11 @@ housekeeping_spi_slave U1 ( .reset(~RSTB), - .SCK(loc_sck), - .SDI(loc_sdi), - .CSB(loc_csb), + .SCK(SCK), + .SDI(SDI), + .CSB(CSB), .SDO(loc_sdo), - .sdoenb(loc_sdoenb), + .sdoenb(sdo_enb), .idata(odata), .odata(idata), .oaddr(iaddr),
diff --git a/verilog/rtl/mgmt_core.v b/verilog/rtl/mgmt_core.v index e6b837b..032d2f5 100644 --- a/verilog/rtl/mgmt_core.v +++ b/verilog/rtl/mgmt_core.v
@@ -34,12 +34,15 @@ input [127:0] la_input, // From Mega-Project to cpu output [127:0] la_output, // From CPU to Mega-Project output [127:0] la_oen, // LA output enable + // Housekeeping SPI + output sdo_out, + output sdo_outenb, + // JTAG + output jtag_out, + output jtag_outenb, // Mega-Project Control Signals - // inout [`MPRJ_IO_PADS-1:0] mgmt_io_data, input [`MPRJ_IO_PADS-1:0] mgmt_in_data, output [`MPRJ_IO_PADS-1:0] mgmt_out_data, - output [`MPRJ_IO_PADS-1:0] mgmt_outz_data, - output [`MPRJ_IO_PADS-1:0] mgmt_oeb_data, output mprj_io_loader_resetn, output mprj_io_loader_clock, output mprj_io_loader_data, @@ -90,16 +93,16 @@ // area pins, when under control of the management area (during // startup, and when not otherwise programmed for the user project). - // JTAG = mgmt_in/out_data[0] (inout) - // SDO = mgmt_out_data[1] (output) (shared with SPI master) + // JTAG = jtag_out (inout) + // SDO = sdo_out (output) (shared with SPI master) // SDI = mgmt_in_data[2] (input) (shared with SPI master) // CSB = mgmt_in_data[3] (input) (shared with SPI master) // SCK = mgmt_in_data[4] (input) (shared with SPI master) // ser_rx = mgmt_in_data[5] (input) // ser_tx = mgmt_out_data[6] (output) // irq = mgmt_in_data[7] (input) - // flash_csb = mgmt_out_data[8] (output) (user area flash) - // flash_sck = mgmt_out_data[9] (output) (user area flash) + // flash_csb = mgmt_out_data[8] (output) (user area flash) + // flash_sck = mgmt_out_data[9] (output) (user area flash) // flash_io0 = mgmt_in/out_data[10] (input) (user area flash) // flash_io1 = mgmt_in/out_data[11] (output) (user area flash) @@ -125,17 +128,7 @@ .gpio_mode1_pad(gpio_mode1_pad), .gpio_outenb_pad(gpio_outenb_pad), .gpio_inenb_pad(gpio_inenb_pad), - // UART - .ser_tx(mgmt_out_data[6]), - .ser_rx(mgmt_in_data[5]), - .irq_pin(mgmt_in_data[7]), .irq_spi(irq_spi), - // SPI master - .spi_csb(mgmt_out_data[3]), - .spi_sck(mgmt_out_data[4]), - .spi_sdi(mgmt_in_data[1]), - .spi_sdo(mgmt_out_data[2]), - .spi_sdoenb(mgmt_oeb_data[2]), // Flash .flash_csb(flash_csb), .flash_clk(flash_clk), @@ -174,11 +167,8 @@ .mprj_io_loader_clock(mprj_io_loader_clock), .mprj_io_loader_data(mprj_io_loader_data), // I/O data - // .mgmt_io_data(mgmt_io_data), .mgmt_in_data(mgmt_in_data), .mgmt_out_data(mgmt_out_data), - .mgmt_outz_data(mgmt_outz_data), - .mgmt_oeb_data(mgmt_oeb_data), // Mega Project Slave ports (WB MI A) .mprj_cyc_o(mprj_cyc_o), .mprj_stb_o(mprj_stb_o), @@ -216,6 +206,9 @@ .ext_trim(spi_pll_trim) ); + // JTAG (to be implemented) + wire jtag_out = 1'b0; + wire jtag_outenb = 1'b1; // Housekeeping SPI vectors wire [4:0] spi_pll_div; @@ -232,16 +225,8 @@ .SCK(mgmt_in_data[4]), .SDI(mgmt_in_data[2]), .CSB(mgmt_in_data[3]), - .SDO(mgmt_out_data[1]), - .sdo_enb(mgmt_oeb_data[1]), - // Note that the Soc SPI master shares pins with the housekeeping - // SPI but with SDI and SDO reversed, such that the CPU can - // access the housekeeping SPI registers directly if the - // SPI master is enabled. - .mgmt_sck(mgmt_in_data[4]), - .mgmt_sdi(mgmt_in_data[1]), - .mgmt_csb(mgmt_in_data[3]), - .mgmt_sdo(mgmt_out_data[2]), + .SDO(sdo_out), + .sdo_enb(sdo_outenb), .pll_dco_ena(spi_pll_dco_ena), .pll_sel(spi_pll_sel), .pll_div(spi_pll_div),
diff --git a/verilog/rtl/mgmt_soc.v b/verilog/rtl/mgmt_soc.v index ce43250..0de30f2 100644 --- a/verilog/rtl/mgmt_soc.v +++ b/verilog/rtl/mgmt_soc.v
@@ -76,25 +76,10 @@ output mprj_io_loader_data, // Mega-Project pad data (when management SoC controls the pad) - // inout [MPRJ_IO_PADS-1:0] mgmt_io_data, input [MPRJ_IO_PADS-1:0] mgmt_in_data, output [MPRJ_IO_PADS-1:0] mgmt_out_data, - output [MPRJ_IO_PADS-1:0] mgmt_outz_data, - output [MPRJ_IO_PADS-1:0] mgmt_oeb_data, - - // SPI master - output spi_csb, - output spi_sck, - output spi_sdo, - output spi_sdoenb, - input spi_sdi, - - // UART - output ser_tx, - input ser_rx, // IRQ - input irq_pin, // dedicated IRQ pin input irq_spi, // IRQ from standalone SPI // Flash memory control (SPI master) @@ -255,6 +240,27 @@ {RAM_BASE_ADR} }; + // The following functions are connected to specific user project + // area pins, when under control of the management area (during + // startup, and when not otherwise programmed for the user project). + + // JTAG = jtag_out (inout) + // SDO = sdo_out (output) (shared with SPI master) + // SDI = mgmt_in_data[2] (input) (shared with SPI master) + // CSB = mgmt_in_data[3] (input) (shared with SPI master) + // SCK = mgmt_in_data[4] (input) (shared with SPI master) + // ser_rx = mgmt_in_data[5] (input) + // ser_tx = mgmt_out_data[6] (output) + // irq_pin = mgmt_in_data[7] (input) + // flash_csb = mgmt_out_data[8] (output) (user area flash) + // flash_sck = mgmt_out_data[9] (output) (user area flash) + // flash_io0 = mgmt_in/out_data[10] (input) (user area flash) + // flash_io1 = mgmt_in/out_data[11] (output) (user area flash) + + // OEB lines for [0] and [1] are the only ones connected directly to + // the pad. All others have OEB controlled by the configuration bit + // in the control block. + // memory-mapped I/O control registers wire gpio_pullup; // Intermediate GPIO pullup wire gpio_pulldown; // Intermediate GPIO pulldown @@ -272,11 +278,8 @@ // GPIO assignments assign gpio_out = (trap_output_dest == 1'b1) ? trap : gpio; - assign gpio_outenb = (trap_output_dest == 1'b0) ? gpio_oeb : 1'b0; - assign gpio_pullup = (trap_output_dest == 1'b0) ? gpio_pu : 1'b0; - assign gpio_pulldown = (trap_output_dest == 1'b0) ? gpio_pd : 1'b0; // Convert GPIO signals to sky130_fd_io pad signals @@ -301,13 +304,12 @@ wire irq_counter_timer1; assign irq_stall = 0; - assign irq_7 = (irq_7_inputsrc == 1'b1) ? gpio_in_pad : 1'b0; + assign irq_7 = (irq_7_inputsrc == 1'b1) ? mgmt_in_data[7] : 1'b0; always @* begin irq = 0; irq[3] = irq_stall; irq[4] = irq_uart; - irq[5] = irq_pin; irq[6] = irq_spi; irq[7] = irq_7; irq[9] = irq_spi_master; @@ -430,6 +432,7 @@ wire uart_stb_i; wire uart_ack_o; wire [31:0] uart_dat_o; + wire uart_enabled; simpleuart_wb #( .BASE_ADR(UART_BASE_ADR), @@ -450,8 +453,9 @@ .wb_ack_o(uart_ack_o), .wb_dat_o(uart_dat_o), + .uart_enabled(uart_enabled), .ser_tx(ser_tx), - .ser_rx(ser_rx) + .ser_rx(mgmt_in_data[5]) ); // Wishbone SPI master @@ -478,11 +482,11 @@ .wb_ack_o(spi_master_ack_o), .wb_dat_o(spi_master_dat_o), - .csb(spi_csb), - .sck(spi_sck), - .sdi(spi_sdi), - .sdo(spi_sdo), - .sdoenb(spi_sdoenb), + .csb(mgmt_out_pre[3]), + .sck(mgmt_out_pre[4]), + .sdi(mgmt_in_data[1]), + .sdo(mgmt_out_pre[2]), + .sdoenb(), .irq(irq_spi_master) ); @@ -635,6 +639,15 @@ wire mprj_ctrl_stb_i; wire mprj_ctrl_ack_o; wire [31:0] mprj_ctrl_dat_o; + wire [31:0] mgmt_out_pre; + + // Bits assigned to specific functions as outputs prevent the + // mprj GPIO-as-output from applying data when that function + // is active + + assign mgmt_out_data[MPRJ_IO_PADS-1:7] = mgmt_out_pre[MPRJ_IO_PADS-1:7]; + assign mgmt_out_data[6] = uart_enabled ? ser_tx : mgmt_out_pre[6]; + assign mgmt_out_data[5:0] = mgmt_out_pre[5:0]; mprj_ctrl_wb #( .BASE_ADR(MPRJ_CTRL_ADR), @@ -656,11 +669,8 @@ .serial_clock(mprj_io_loader_clock), .serial_resetn(mprj_io_loader_resetn), .serial_data_out(mprj_io_loader_data), - // .mgmt_gpio_io(mgmt_io_data) - .mgmt_gpio_in(mgmt_in_data), - .mgmt_gpio_out(mgmt_out_data), - .mgmt_gpio_outz(mgmt_outz_data), - .mgmt_gpio_oeb(mgmt_oeb_data) + .mgmt_gpio_out(mgmt_out_pre), + .mgmt_gpio_in(mgmt_in_data) ); // Wishbone Slave RAM
diff --git a/verilog/rtl/mprj_ctrl.v b/verilog/rtl/mprj_ctrl.v index 035e756..117fcfe 100644 --- a/verilog/rtl/mprj_ctrl.v +++ b/verilog/rtl/mprj_ctrl.v
@@ -26,9 +26,7 @@ // Read/write data to each GPIO pad from management SoC input [IO_PADS-1:0] mgmt_gpio_in, - output [IO_PADS-1:0] mgmt_gpio_out, - output [IO_PADS-1:0] mgmt_gpio_outz, - output [IO_PADS-1:0] mgmt_gpio_oeb // Only JTAG and SDO connected + output [IO_PADS-1:0] mgmt_gpio_out ); wire resetn; wire valid; @@ -63,9 +61,7 @@ .serial_data_out(serial_data_out), // .mgmt_gpio_io(mgmt_gpio_io) .mgmt_gpio_in(mgmt_gpio_in), - .mgmt_gpio_out(mgmt_gpio_out), - .mgmt_gpio_outz(mgmt_gpio_outz), - .mgmt_gpio_oeb(mgmt_gpio_oeb) + .mgmt_gpio_out(mgmt_gpio_out) ); endmodule @@ -94,9 +90,7 @@ output serial_resetn, output serial_data_out, input [IO_PADS-1:0] mgmt_gpio_in, - output [IO_PADS-1:0] mgmt_gpio_out, - output [IO_PADS-1:0] mgmt_gpio_outz, - output [IO_PADS-1:0] mgmt_gpio_oeb + output [IO_PADS-1:0] mgmt_gpio_out ); `define IDLE 2'b00 @@ -111,9 +105,8 @@ reg [IO_CTRL_BITS-1:0] io_ctrl[IO_PADS-1:0]; // I/O control, 1 word per gpio pad reg [PWR_CTRL_BITS-1:0] pwr_ctrl[PWR_PADS-1:0]; // Power control, 1 word per power pad - reg [IO_PADS-1:0] mgmt_gpio_out; // I/O write data, 1 bit per gpio pad - wire [IO_PADS-1:0] mgmt_gpio_outz; // I/O write data output when input disabled - wire [IO_PADS-1:0] mgmt_gpio_oeb; + reg [IO_PADS-1:0] mgmt_gpio_outr; // I/O write data, 1 bit per gpio pad + wire [IO_PADS-1:0] mgmt_gpio_out; // I/O write data output when input disabled reg xfer_ctrl; // Transfer control (1 bit) wire [IO_PADS-1:0] io_ctrl_sel; // wishbone selects @@ -129,12 +122,8 @@ generate for (i=0; i<IO_PADS; i=i+1) begin assign io_ctrl_sel[i] = (iomem_addr[7:0] == (IO_BASE_ADR[7:0] + i*4)); - // OEB is both tranferred by serial chain and output; that way - // each pad can selectively choose whether to have a dedicated - // signal for OEB, or to use it as a static configuration bit. - assign mgmt_gpio_oeb[i] = io_ctrl[i][OEB]; - assign mgmt_gpio_outz[i] = (io_ctrl[i][INP_DIS] == 1'b1) ? - mgmt_gpio_out[i] : 1'bz; + assign mgmt_gpio_out[i] = (io_ctrl[i][INP_DIS] == 1'b1) ? + mgmt_gpio_outr[i] : 1'bz; end endgenerate @@ -150,7 +139,7 @@ always @(posedge clk) begin if (!resetn) begin xfer_ctrl <= 0; - mgmt_gpio_out <= 'd0; + mgmt_gpio_outr <= 'd0; end else begin iomem_ready <= 0; if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin @@ -159,7 +148,7 @@ if (io_data_sel) begin iomem_rdata <= mgmt_gpio_in; if (iomem_wstrb[0]) begin - mgmt_gpio_out[IO_PADS-1:0] <= iomem_wdata[IO_PADS-1:0]; + mgmt_gpio_outr[IO_PADS-1:0] <= iomem_wdata[IO_PADS-1:0]; end end else if (xfer_sel) begin
diff --git a/verilog/rtl/simple_spi_master.v b/verilog/rtl/simple_spi_master.v index dad5471..a2a33b6 100755 --- a/verilog/rtl/simple_spi_master.v +++ b/verilog/rtl/simple_spi_master.v
@@ -185,7 +185,7 @@ // No bidirectional 3-pin mode defined, so SDO is enabled whenever CSB is low. assign sdoenb = icsb; // assign sdo = (enable == 1'b0) ? 1'bz : icsb ? 1'bz : isdo; - assign sdo = isdo; + assign sdo = (enable == 1'b0) ? 1'bz : isdo; assign irq_out = irqena & done;
diff --git a/verilog/rtl/simpleuart.v b/verilog/rtl/simpleuart.v index 51e95c7..54a3cb4 100644 --- a/verilog/rtl/simpleuart.v +++ b/verilog/rtl/simpleuart.v
@@ -20,7 +20,8 @@ module simpleuart_wb # ( parameter BASE_ADR = 32'h 2000_0000, parameter CLK_DIV = 8'h00, - parameter DATA = 8'h04 + parameter DATA = 8'h04, + parameter CONFIG = 8'h08 ) ( input wb_clk_i, input wb_rst_i, @@ -35,26 +36,33 @@ output wb_ack_o, output [31:0] wb_dat_o, + output uart_enabled, output ser_tx, input ser_rx ); wire [31:0] simpleuart_reg_div_do; wire [31:0] simpleuart_reg_dat_do; + wire [31:0] simpleuart_reg_cfg_do; wire resetn = ~wb_rst_i; wire valid = wb_stb_i && wb_cyc_i; wire simpleuart_reg_div_sel = valid && (wb_adr_i == (BASE_ADR | CLK_DIV)); wire simpleuart_reg_dat_sel = valid && (wb_adr_i == (BASE_ADR | DATA)); + wire simpleuart_reg_cfg_sel = valid && (wb_adr_i == (BASE_ADR | CONFIG)); - 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 + wire [3:0] reg_div_we = simpleuart_reg_div_sel ? (wb_sel_i & {4{wb_we_i}}): 4'b 0000; 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 + wire reg_cfg_we = simpleuart_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 = simpleuart_reg_dat_sel && !wb_sel_i && ~wb_we_i; // read_enable - assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do: simpleuart_reg_dat_do; - assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel) && (!reg_dat_wait); + assign wb_dat_o = simpleuart_reg_div_sel ? simpleuart_reg_div_do: + simpleuart_reg_cfg_sel ? simpleuart_reg_cfg_do: + simpleuart_reg_dat_do; + assign wb_ack_o = (simpleuart_reg_div_sel || simpleuart_reg_dat_sel + || simpleuart_reg_cfg_sel) && (!reg_dat_wait); simpleuart simpleuart ( .clk (wb_clk_i), @@ -62,11 +70,16 @@ .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 (simpleuart_reg_div_do), + .reg_cfg_we (reg_cfg_we), + .reg_cfg_di (mem_wdata), + .reg_cfg_do (simpleuart_reg_cfg_do), + .reg_dat_we (reg_dat_we), .reg_dat_re (reg_dat_re), .reg_dat_di (mem_wdata), @@ -80,6 +93,7 @@ input clk, input resetn, + output enabled, output ser_tx, input ser_rx, @@ -87,6 +101,10 @@ 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, @@ -94,6 +112,7 @@ output reg_dat_wait ); reg [31:0] cfg_divider; + reg enabled; reg [3:0] recv_state; reg [31:0] recv_divcnt; @@ -107,6 +126,7 @@ reg send_dummy; assign reg_div_do = cfg_divider; + assign reg_ena_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; @@ -114,11 +134,13 @@ 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]; end end @@ -135,7 +157,7 @@ recv_buf_valid <= 0; case (recv_state) 0: begin - if (!ser_rx) + if (!ser_rx && enabled) recv_state <= 1; recv_divcnt <= 0; end @@ -166,7 +188,7 @@ assign ser_tx = send_pattern[0]; always @(posedge clk) begin - if (reg_div_we) + if (reg_div_we && enabled) send_dummy <= 1; send_divcnt <= send_divcnt + 1; if (!resetn) begin