From 4e3df09bb8feec86a3dd748b789719de71212ef9 Mon Sep 17 00:00:00 2001 From: Peter McGoron Date: Thu, 8 Feb 2024 12:57:22 +0000 Subject: [PATCH] more cleanup and bug finding --- .gitignore | 7 - build/Dockerfile.hardware | 1 + build/Makefile | 4 +- gateware/Makefile | 8 +- gateware/rtl/Makefile | 26 +- gateware/rtl/base/Makefile | 9 - gateware/rtl/base/base.v.m4 | 396 ------------------ gateware/rtl/bram/Makefile | 15 - gateware/rtl/bram/{bram.v.m4 => bram.v} | 42 +- gateware/rtl/picorv32/picorv32.v | 11 +- gateware/rtl/spi/spi_master_ss_wb.v | 2 +- gateware/soc.py | 524 ++++++++++++------------ 12 files changed, 304 insertions(+), 741 deletions(-) delete mode 100644 gateware/rtl/base/Makefile delete mode 100644 gateware/rtl/base/base.v.m4 delete mode 100644 gateware/rtl/bram/Makefile rename gateware/rtl/bram/{bram.v.m4 => bram.v} (66%) diff --git a/.gitignore b/.gitignore index 920758e..d7692fa 100644 --- a/.gitignore +++ b/.gitignore @@ -35,17 +35,10 @@ gateware/csr_bitwidth.json boot/* !boot/boot.json *.tar.gz -build/buildroot.tar.gz build/buildroot/ build/f4pga/ build/litex/ build/opensbi/ build/upsilon/ -build/upsilon.tar.gz -build/f4pga.tar.gz -build/opensbi.tar.gz -build/upsilon-opensbi.tar.gz -build/upsilon-hardware.tar.gz -build/upsilon-buildroot.tar.gz swic/*.bin swic/*.elf diff --git a/build/Dockerfile.hardware b/build/Dockerfile.hardware index e89d901..7b628b4 100644 --- a/build/Dockerfile.hardware +++ b/build/Dockerfile.hardware @@ -30,6 +30,7 @@ COPY --chown=user:user f4pga.tar.gz /home/user RUN tar -xvf f4pga.tar.gz \ && rm f4pga.tar.gz \ && cd f4pga/f4pga \ +# && sed -i 's/-abc9//g' ./wrappers/tcl/xc7.f4pga.tcl \ && bash -c 'source ~/conda/xc7/conda/etc/profile.d/conda.sh; conda activate xc7; pip install . ninja meson' #LITEX diff --git a/build/Makefile b/build/Makefile index 87b0ef8..fb88b92 100644 --- a/build/Makefile +++ b/build/Makefile @@ -35,9 +35,9 @@ hardware-copy: upsilon-hardware.tar.gz # XXX: this always fails if there are very high UIDs, but the # file is copied successfully. -docker cp upsilon-hardware.tar.gz upsilon-hardware:/home/user/upsilon-hardware.tar.gz + docker exec -ti upsilon-hardware tar -xvf upsilon-hardware.tar.gz hardware-execute: docker exec -ti upsilon-hardware /bin/bash -lc ' \ - tar -xvf upsilon-hardware.tar.gz && \ cd upsilon/gateware && \ source ~/conda/xc7/conda/etc/profile.d/conda.sh && \ conda activate xc7 && \ @@ -49,7 +49,7 @@ hardware-get: docker cp upsilon-hardware:/home/user/upsilon/gateware/arty.dtb ../boot/ # docker cp upsilon-hardware:/home/user/upsilon/gateware/mmio.py ../boot/ docker cp upsilon-hardware:/home/user/upsilon/gateware/csr.json ../boot/ - docker cp upsilon-hardware:/home/user/upsilon/gateware/picorv32.json ../boot/ +# docker cp upsilon-hardware:/home/user/upsilon/gateware/picorv32.json ../boot/ hardware-clean: -docker container stop upsilon-hardware -docker container rm upsilon-hardware diff --git a/gateware/Makefile b/gateware/Makefile index a04075f..7769f13 100644 --- a/gateware/Makefile +++ b/gateware/Makefile @@ -8,19 +8,13 @@ DEVICETREE_GEN_DIR=. -all: rtl_codegen build/digilent_arty/digilent_arty.bit arty.dtb# mmio.py - -rtl_codegen: - cd rtl && make +all: build/digilent_arty/digilent_arty.bit arty.dtb# mmio.py csr.json build/digilent_arty/digilent_arty.bit: soc.py python3 soc.py clean: rm -rf build csr.json arty.dts arty.dtb mmio.py - cd rtl && make clean -test: - cd rtl && make test arty.dts: csr.json litex_json2dts_linux csr.json > arty.dts diff --git a/gateware/rtl/Makefile b/gateware/rtl/Makefile index a413179..48491e9 100644 --- a/gateware/rtl/Makefile +++ b/gateware/rtl/Makefile @@ -3,22 +3,12 @@ # For license terms, refer to the files in `doc/copying` in the Upsilon # source distribution. -all: make_base make_spi make_control_loop make_bram +#all: make_bram -test: - cd control_loop && make test -make_base: - cd base && make codegen -make_spi: - cd spi && make codegen -make_control_loop: - cd control_loop && make codegen -make_waveform: - cd waveform && make codegen -make_bram: - cd bram && make codegen -clean: - cd base && make clean - cd spi && make clean - cd control_loop && make clean - cd waveform && make clean +dummy: + @echo empty + +#make_bram: +# cd bram && make codegen +#clean: +# cd bram && make clean diff --git a/gateware/rtl/base/Makefile b/gateware/rtl/base/Makefile deleted file mode 100644 index 528ea37..0000000 --- a/gateware/rtl/base/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -.PHONY: lint -include ../common.makefile - -codegen: base.v -base.v: base.v.m4 -lint: base.v - verilator --lint-only base.v -I../spi -I../control_loop -I../waveform -clean: - rm -f base.v diff --git a/gateware/rtl/base/base.v.m4 b/gateware/rtl/base/base.v.m4 deleted file mode 100644 index 2c328f4..0000000 --- a/gateware/rtl/base/base.v.m4 +++ /dev/null @@ -1,396 +0,0 @@ -m4_changequote(`⟨', `⟩') -m4_changecom(⟨/*⟩, ⟨*/⟩) -m4_define(generate_macro, ⟨m4_define(M4_$1, $2)⟩) -/* -Copyright 2023 (C) Peter McGoron - -This file is a part of Upsilon, a free and open source software project. -For license terms, refer to the files in `doc/copying` in the Upsilon -source distribution. -_____________________________________________________________________ - -This is the module that collects all Verilog and exports a single interface -that is connected to the CPU by LiteX. - -In this future, this module should be written into soc.py - -Since yosys only allows for standard Verilog (no system verilog), -arrays (which would make everything much cleaner) cannot be used. -A preprocessor is used instead, and M4 is used because it is much -cleaner than the Verilog preprocessor (which is bad). -TODO: individual RST pins -*/ - -/*********************************************************/ -/********************** M4 macros ************************/ -/*********************************************************/ - -/* This macro is used in the module declaration. - * The first argument is the number of wires the select switch must - * support (2 for most DACs, 3 for the control loop DAC). - * The second argument is the DAC number. - */ -m4_define(m4_dac_wires, ⟨ - input [$1-1:0] dac_sel_$2, - output dac_finished_$2, - input dac_arm_$2, - output [DAC_WID-1:0] dac_recv_buf_$2, - input [DAC_WID-1:0] dac_send_buf_$2 - -/* - input wf_arm_$2, - input wf_halt_on_finish_$2, - output wf_finished_$2, - input [WF_TIMER_WID-1:0] wf_time_to_wait_$2, - input wf_refresh_start_$2, - input [WF_RAM_WID-1:0] wf_start_addr_$2, - output wf_refresh_finished_$2, - output wf_running_$2, - - output [WF_RAM_WID-1:0] wf_ram_dma_addr_$2, - input [WF_RAM_WORD_WID-1:0] wf_ram_word_$2, - output wf_ram_read_$2, - input wf_ram_valid_$2 -*/ -⟩) - -/* Same thing but for ADCs */ - -m4_define(m4_adc_wires, ⟨ - input [$3-1:0] adc_sel_$2, - output adc_finished_$2, - input adc_arm_$2, - output [$1-1:0] adc_recv_buf_$2 -⟩) - -/* This is used in the body of the module. It declares the interconnect - * for each DAC. The first argument is the amount of switch ports the - * DAC requires (2 for most DACs, 3 for the control loop DAC). The - * second argument is the DAC number. - */ - -m4_define(m4_dac_switch, ⟨ - wire [$1-1:0] mosi_port_$2; - wire [$1-1:0] miso_port_$2; - wire [$1-1:0] sck_port_$2; - wire [$1-1:0] ss_L_port_$2; - - spi_switch #( - .PORTS($1) - ) switch_$2 ( - .select(dac_sel_$2), - .mosi(dac_mosi[$2]), - .miso(dac_miso[$2]), - .sck(dac_sck[$2]), - .ss_L(dac_ss_L[$2]), - - .mosi_ports(mosi_port_$2), - .miso_ports(miso_port_$2), - .sck_ports(sck_port_$2), - .ss_L_ports(ss_L_port_$2) - ); - - spi_master_ss #( - .WID(DAC_WID), - .WID_LEN(DAC_WID_SIZ), - .CYCLE_HALF_WAIT(DAC_CYCLE_HALF_WAIT), - .TIMER_LEN(DAC_CYCLE_HALF_WAIT_SIZ), - .POLARITY(DAC_POLARITY), - .PHASE(DAC_PHASE), - .SS_WAIT(DAC_SS_WAIT), - .SS_WAIT_TIMER_LEN(DAC_SS_WAIT_SIZ) - ) dac_master_$2 ( - .clk(clk), - .rst_L(rst_L), - .mosi(mosi_port_$2[0]), - .miso(miso_port_$2[0]), - .sck_wire(sck_port_$2[0]), - .ss_L(ss_L_port_$2[0]), - .finished(dac_finished_$2), - .arm(dac_arm_$2), - .from_slave(dac_recv_buf_$2), - .to_slave(dac_send_buf_$2) - ) - -/* - waveform #( - .DAC_WID(DAC_WID), - .DAC_WID_SIZ(DAC_WID_SIZ), - .DAC_POLARITY(DAC_POLARITY), - .DAC_PHASE(DAC_PHASE), - .DAC_CYCLE_HALF_WAIT(DAC_CYCLE_HALF_WAIT), - .DAC_CYCLE_HALF_WAIT_SIZ(DAC_CYCLE_HALF_WAIT_SIZ), - .DAC_SS_WAIT(DAC_SS_WAIT), - .DAC_SS_WAIT_SIZ(DAC_SS_WAIT_SIZ), - .TIMER_WID(WF_TIMER_WID), - .WORD_WID(WF_WORD_WID), - .WORD_AMNT_WID(WF_WORD_AMNT_WID), - .WORD_AMNT(WF_WORD_AMNT), - .RAM_WID(WF_RAM_WID), - .RAM_WORD_WID(WF_RAM_WORD_WID), - .RAM_WORD_INCR(WF_RAM_WORD_INCR) - ) waveform_$2 ( - .clk(clk), - .arm(wf_arm_$2), - .halt_on_finish(wf_halt_on_finish_$2), - .running(wf_running_$2), - .finished(wf_finished_$2), - .time_to_wait(wf_time_to_wait_$2), - .refresh_start(wf_refresh_start_$2), - .start_addr(wf_start_addr_$2), - .refresh_finished(wf_refresh_finished_$2), - .ram_dma_addr(wf_ram_dma_addr_$2), - .ram_word(wf_ram_word_$2), - .ram_read(wf_ram_read_$2), - .ram_valid(wf_ram_valid_$2), - .mosi(mosi_port_$2[1]), - .sck(sck_port_$2[1]), - .ss_L(ss_L_port_$2[1]) - ) -*/ -⟩) - -/* Same thing but for ADCs */ - -m4_define(m4_adc_switch, ⟨ - wire adc_mosi_unused_output_$2; - wire [$3-1:0] adc_mosi_port_$2; /* Unused! */ - wire [$3-1:0] adc_sdo_port_$2; - wire [$3-1:0] adc_sck_port_$2; - wire [$3-1:0] adc_conv_L_port_$2; - - spi_switch #( - .PORTS($3) - ) adc_switch_$2 ( - .select(adc_sel_$2), - .mosi(adc_mosi_unused_output_$2), - .miso(adc_sdo[$2]), - .sck(adc_sck[$2]), - .ss_L(adc_conv_L[$2]), - - .mosi_ports(adc_mosi_port_$2), - .miso_ports(adc_sdo_port_$2), - .sck_ports(adc_sck_port_$2), - .ss_L_ports(adc_conv_L_port_$2) - ); - - spi_master_ss_no_write #( - .WID($1), - .WID_LEN(ADC_WID_SIZ), - .CYCLE_HALF_WAIT(ADC_CYCLE_HALF_WAIT), - .TIMER_LEN(ADC_CYCLE_HALF_WAIT_SIZ), - .SS_WAIT(ADC_CONV_WAIT), - .SS_WAIT_TIMER_LEN(ADC_CONV_WAIT_SIZ), - .POLARITY(ADC_POLARITY), - .PHASE(ADC_PHASE) - ) adc_master_$2 ( - .clk(clk), - .rst_L(rst_L), - .miso(adc_sdo_port_$2[0]), - .sck_wire(adc_sck_port_$2[0]), - .ss_L(adc_conv_L_port_$2[0]), - .finished(adc_finished_$2), - .arm(adc_arm_$2), - .from_slave(adc_recv_buf_$2) - ); - -/* 2nd option for each ADC is the non-converting option. - * This is used to flush output from reset ADCs. - * TODO: Lower power consumption by having SCK low while converter is - * not running? May require change to spi code. - */ - assign adc_sdo_port[1] = adc_sdo_port[0]; - assign adc_sck_port[1] = adc_sck_port[0]; - assign adc_conv_L_port[1] = 1; -⟩) - -/*********************************************************/ -/*********************** Verilog *************************/ -/*********************************************************/ - -module base #( - parameter DAC_PORTS = 1, -m4_define(DAC_PORTS_CONTROL_LOOP, (DAC_PORTS + 1)) - - parameter DAC_NUM = 8, // Number of DACs - parameter DAC_WID = 24, // Bit width of DAC command - parameter DAC_DATA_WID = 20, // Bit with of DAC register - parameter DAC_WID_SIZ = 5, // number of bits required to store DAC_DATA_WID - parameter DAC_POLARITY = 0, // DAC SCK polarity - parameter DAC_PHASE = 1, // DAC SCK phase - parameter DAC_CYCLE_HALF_WAIT = 10, - parameter DAC_CYCLE_HALF_WAIT_SIZ = 4, - parameter DAC_SS_WAIT = 5, - parameter DAC_SS_WAIT_SIZ = 3, - parameter WF_TIMER_WID = 32, - parameter WF_WORD_WID = 20, - parameter WF_WORD_AMNT_WID = 11, - parameter [WF_WORD_AMNT_WID-1:0] WF_WORD_AMNT = 2047, - parameter WF_RAM_WID = 32, - parameter WF_RAM_WORD_WID = 16, - parameter WF_RAM_WORD_INCR = 2, - - parameter ADC_PORTS = 2, -m4_define(ADC_PORTS_CONTROL_LOOP, (ADC_PORTS + 1)) - parameter ADC_NUM = 8, - /* Three types of ADC. For now assume that their electronics - * are similar enough, just need different numbers for the width. - */ - parameter ADC_TYPE1_WID = 18, - parameter ADC_TYPE2_WID = 16, - parameter ADC_TYPE3_WID = 24, - parameter ADC_WID_SIZ = 5, - parameter ADC_CYCLE_HALF_WAIT = 5, - parameter ADC_CYCLE_HALF_WAIT_SIZ = 3, - parameter ADC_POLARITY = 1, - parameter ADC_PHASE = 0, - /* The ADC takes maximum 527 ns to capture a value. - * The clock ticks at 10 ns. Change for different clocks! - */ - parameter ADC_CONV_WAIT = 60, - parameter ADC_CONV_WAIT_SIZ = 6, - - parameter CL_CONSTS_WHOLE = 21, - parameter CL_CONSTS_FRAC = 43, - parameter CL_CONSTS_SIZ = 7, - parameter CL_DELAY_WID = 16, -m4_define(CL_CONSTS_WID, (CL_CONSTS_WHOLE + CL_CONSTS_FRAC)) -m4_define(CL_DATA_WID, CL_CONSTS_WID) - parameter CL_READ_DAC_DELAY = 5, - parameter CL_CYCLE_COUNT_WID = 18 -) ( - input clk, - input rst_L, - output [11-1:0] set_low, - - output [DAC_NUM-1:0] dac_mosi, - input [DAC_NUM-1:0] dac_miso, - output [DAC_NUM-1:0] dac_sck, - output [DAC_NUM-1:0] dac_ss_L, - - output [ADC_NUM-1:0] adc_conv, - input [ADC_NUM-1:0] adc_sdo, - output [ADC_NUM-1:0] adc_sck, - - m4_dac_wires(DAC_PORTS_CONTROL_LOOP, 0), - m4_dac_wires(DAC_PORTS, 1), - m4_dac_wires(DAC_PORTS, 2), - m4_dac_wires(DAC_PORTS, 3), - m4_dac_wires(DAC_PORTS, 4), - m4_dac_wires(DAC_PORTS, 5), - m4_dac_wires(DAC_PORTS, 6), - m4_dac_wires(DAC_PORTS, 7), - - m4_adc_wires(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP), - m4_adc_wires(ADC_TYPE1_WID, 1, ADC_PORTS), - m4_adc_wires(ADC_TYPE1_WID, 2, ADC_PORTS), - m4_adc_wires(ADC_TYPE2_WID, 3, ADC_PORTS), - m4_adc_wires(ADC_TYPE2_WID, 4, ADC_PORTS), - m4_adc_wires(ADC_TYPE2_WID, 5, ADC_PORTS), - m4_adc_wires(ADC_TYPE3_WID, 6, ADC_PORTS), - m4_adc_wires(ADC_TYPE3_WID, 7, ADC_PORTS), - - input cl_assert_change, - output cl_change_made, - output cl_in_loop, - - input cl_run_loop_in, - input [ADC_TYPE1_WID-1:0] cl_setpt_in, - input [CL_DATA_WID-1:0] cl_P_in, - input [CL_DATA_WID-1:0] cl_I_in, - input [CL_DELAY_WID-1:0] cl_delay_in, - - output [CL_CYCLE_COUNT_WID-1:0] cl_cycle_count, - output [DAC_DATA_WID-1:0] cl_z_pos, - output [ADC_TYPE1_WID-1:0] cl_z_measured -); - -assign set_low = 0; - -wire [ADC_NUM-1:0] adc_conv_L; -assign adc_conv = ~adc_conv_L; - -m4_dac_switch(DAC_PORTS_CONTROL_LOOP, 0); -m4_dac_switch(DAC_PORTS, 1); -m4_dac_switch(DAC_PORTS, 2); -m4_dac_switch(DAC_PORTS, 3); -m4_dac_switch(DAC_PORTS, 4); -m4_dac_switch(DAC_PORTS, 5); -m4_dac_switch(DAC_PORTS, 6); -m4_dac_switch(DAC_PORTS, 7); - -`define MAKE_TEST_CLOCK -`ifdef MAKE_TEST_CLOCK -reg [8-1:0] counter = 0; -always @ (posedge clk) begin - if (!rst_L) begin - counter <= 0; - test_clock <= 0; - end else begin - if (counter == ADC_CYCLE_HALF_WAIT) begin - counter <= 0; - test_clock <= !test_clock; - end else begin - counter <= counter + 1; - end - end -end -`endif - -m4_adc_switch(ADC_TYPE1_WID, 0, ADC_PORTS_CONTROL_LOOP); -m4_adc_switch(ADC_TYPE1_WID, 1, ADC_PORTS); -m4_adc_switch(ADC_TYPE1_WID, 2, ADC_PORTS); -m4_adc_switch(ADC_TYPE1_WID, 3, ADC_PORTS); -m4_adc_switch(ADC_TYPE1_WID, 4, ADC_PORTS); -m4_adc_switch(ADC_TYPE1_WID, 5, ADC_PORTS); -m4_adc_switch(ADC_TYPE1_WID, 6, ADC_PORTS); -m4_adc_switch(ADC_TYPE1_WID, 7, ADC_PORTS); - -control_loop #( - .ADC_WID(ADC_TYPE1_WID), - .ADC_WID_SIZ(ADC_WID_SIZ), - .ADC_CYCLE_HALF_WAIT(ADC_CYCLE_HALF_WAIT), - .ADC_CYCLE_HALF_WAIT_SIZ(ADC_CYCLE_HALF_WAIT_SIZ), - .ADC_POLARITY(ADC_POLARITY), - .ADC_PHASE(ADC_PHASE), - .ADC_CONV_WAIT(ADC_CONV_WAIT), - .ADC_CONV_WAIT_SIZ(ADC_CONV_WAIT_SIZ), - .CONSTS_WHOLE(CL_CONSTS_WHOLE), - .CONSTS_FRAC(CL_CONSTS_FRAC), - .CONSTS_SIZ(CL_CONSTS_SIZ), - .DELAY_WID(CL_DELAY_WID), - .READ_DAC_DELAY(CL_READ_DAC_DELAY), - .CYCLE_COUNT_WID(CL_CYCLE_COUNT_WID), - .DAC_WID(DAC_WID), - .DAC_WID_SIZ(DAC_WID_SIZ), - .DAC_DATA_WID(DAC_DATA_WID), - .DAC_POLARITY(DAC_POLARITY), - .DAC_PHASE(DAC_PHASE), - .DAC_CYCLE_HALF_WAIT(DAC_CYCLE_HALF_WAIT), - .DAC_CYCLE_HALF_WAIT_SIZ(DAC_CYCLE_HALF_WAIT_SIZ), - .DAC_SS_WAIT(DAC_SS_WAIT), - .DAC_SS_WAIT_SIZ(DAC_SS_WAIT_SIZ) -) cl ( - .clk(clk), - .rst_L(rst_L), - .in_loop(cl_in_loop), - .dac_mosi(mosi_port_0[1]), - .dac_miso(miso_port_0[1]), - .dac_ss_L(ss_L_port_0[1]), - .dac_sck(sck_port_0[1]), - .adc_miso(adc_sdo_port_0[2]), - .adc_conv_L(adc_conv_L_port_0[2]), - .adc_sck(adc_sck_port_0[2]), - .assert_change(cl_assert_change), - .change_made(cl_change_made), - .run_loop_in(cl_run_loop_in), - .setpt_in(cl_setpt_in), - .P_in(cl_P_in), - .I_in(cl_I_in), - .delay_in(cl_delay_in), - .cycle_count(cl_cycle_count), - .z_pos(cl_z_pos), - .z_measured(cl_z_measured) -); - -endmodule diff --git a/gateware/rtl/bram/Makefile b/gateware/rtl/bram/Makefile deleted file mode 100644 index 1263ca3..0000000 --- a/gateware/rtl/bram/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2024 (C) Peter McGoron -# This file is a part of Upsilon, a free and open source software project. -# For license terms, refer to the files in `doc/copying` in the Upsilon -# source distribution. - -.PHONY: codegen - -all: codegen -####### Codegen ######## - -include ../common.makefile -CODEGEN_FILES=bram.v -codegen: ${CODEGEN_FILES} -clean: - rm -rf obj_dir *.fst ${CODEGEN_FILES} diff --git a/gateware/rtl/bram/bram.v.m4 b/gateware/rtl/bram/bram.v similarity index 66% rename from gateware/rtl/bram/bram.v.m4 rename to gateware/rtl/bram/bram.v index d5dec1b..3815e9b 100644 --- a/gateware/rtl/bram/bram.v.m4 +++ b/gateware/rtl/bram/bram.v @@ -1,6 +1,3 @@ -m4_changequote(`⟨', `⟩') -m4_changecom(⟨/*⟩, ⟨*/⟩) - /* Copyright 2024 (C) Peter McGoron * This file is a part of Upsilon, a free and open source software project. * For license terms, refer to the files in `doc/copying` in the Upsilon @@ -25,9 +22,12 @@ module bram #( input [BUS_WID-1:0] wb_addr, input [BUS_WID-1:0] wb_dat_w, output reg wb_ack, - output reg [BUS_WID-1:0] wb_dat_r, + output reg [BUS_WID-1:0] wb_dat_r ); +initial wb_ack <= 0; +initial wb_dat_r <= 0; + /* When the size of the memory is a power of 2, the mask is the * last addressable index in the array. * @@ -38,33 +38,27 @@ module bram #( * the 32 bit word that contains the address. This applies to halfwords * and words as long as the accesses are aligned. */ +(* ram_style = "block" *) reg [WORD_WID-1:0] buffer [(ADDR_MASK >> 2):0]; /* Current index into the buffer. */ wire [13-1:0] ind = (wb_addr & ADDR_MASK) >> 2; -m4_define(⟨bufwrite⟩, ⟨begin - buffer[ind] <= (buffer[ind] & $1) | wb_dat_w[$2]; -end⟩) - -always @ (posedge clk) if (wb_cyc && wb_stb && !wb_ack) - if (!wb_we) begin - wb_dat_r <= buffer[ind]; - wb_ack <= 1; +always @ (posedge clk) if (wb_cyc && wb_stb && !wb_ack) begin + wb_ack <= 1; + if (wb_we) begin + if (wb_sel[0]) + buffer[ind][7:0] <= wb_dat_w[7:0]; + if (wb_sel[1]) + buffer[ind][15:8] <= wb_dat_w[15:8]; + if (wb_sel[2]) + buffer[ind][23:16] <= wb_dat_w[23:16]; + if (wb_sel[3]) + buffer[ind][31:24] <= wb_dat_w[31:24]; end else begin - wb_ack <= 1; - case (wb_sel) - 4'b1111: buffer[ind] <= wb_dat_w; - 4'b0011: bufwrite(32'hFFFF0000, 15:0) - 4'b1100: bufwrite(32'h0000FFFF, 31:16) - 4'b0001: bufwrite(32'hFFFFFF00, 7:0) - 4'b0010: bufwrite(32'hFFFF00FF, 15:8) - 4'b0100: bufwrite(32'hFF00FFFF, 23:16) - 4'b1000: bufwrite(32'h00FFFFFF, 31:24) - default: ; - endcase + wb_dat_r <= buffer[ind]; end -else if (!wb_stb) begin +end else if (!wb_stb) begin wb_ack <= 0; end diff --git a/gateware/rtl/picorv32/picorv32.v b/gateware/rtl/picorv32/picorv32.v index 8881dad..85b6b8d 100644 --- a/gateware/rtl/picorv32/picorv32.v +++ b/gateware/rtl/picorv32/picorv32.v @@ -2167,6 +2167,7 @@ module picorv32 #( `endif endmodule +`ifdef 0 // This is a simple example implementation of PICORV32_REGS. // Use the PICORV32_REGS mechanism if you want to use custom // memory resources to implement the processor register file. @@ -2315,7 +2316,9 @@ module picorv32_pcpi_mul #( end end endmodule +`endif +`ifdef 0 module picorv32_pcpi_fast_mul #( parameter EXTRA_MUL_FFS = 0, parameter EXTRA_INSN_FFS = 0, @@ -2418,6 +2421,7 @@ endmodule * picorv32_pcpi_div ***************************************************************/ +`ifdef 0 module picorv32_pcpi_div ( input clk, resetn, @@ -2510,11 +2514,13 @@ module picorv32_pcpi_div ( end endmodule +`endif /*************************************************************** * picorv32_axi ***************************************************************/ +`ifdef 0 module picorv32_axi #( parameter [ 0:0] ENABLE_COUNTERS = 1, parameter [ 0:0] ENABLE_COUNTERS64 = 1, @@ -2723,12 +2729,13 @@ module picorv32_axi #( .trace_data (trace_data) ); endmodule - +`endif /*************************************************************** * picorv32_axi_adapter ***************************************************************/ +`ifdef 0 module picorv32_axi_adapter ( input clk, resetn, @@ -2807,7 +2814,7 @@ module picorv32_axi_adapter ( end end endmodule - +`endif /*************************************************************** * picorv32_wb diff --git a/gateware/rtl/spi/spi_master_ss_wb.v b/gateware/rtl/spi/spi_master_ss_wb.v index b5d4ed5..973749c 100644 --- a/gateware/rtl/spi/spi_master_ss_wb.v +++ b/gateware/rtl/spi/spi_master_ss_wb.v @@ -99,7 +99,7 @@ always @ (posedge clk) if (wb_cyc && wb_stb && !wb_ack) begin default: ; endcase wb_ack <= 1; -end else begin +end else if (!wb_cyc) begin wb_ack <= 0; end diff --git a/gateware/soc.py b/gateware/soc.py index 4838cbb..7f7c301 100644 --- a/gateware/soc.py +++ b/gateware/soc.py @@ -92,124 +92,122 @@ If there is more than one pin in the Pins string, the resulting name will be a vector of pins. """ io = [ - ("differntial_output_low", 0, Pins("J17 J18 K15 J15 U14 V14 T13 U13 B6 E5 A3"), IOStandard("LVCMOS33")), - ("dac_ss_L", 0, Pins("G13 D13 E15 F5 U12 D7 D4 E2"), IOStandard("LVCMOS33")), - ("dac_mosi", 0, Pins("B11 B18 E16 D8 V12 D5 D3 D2"), IOStandard("LVCMOS33")), - ("dac_miso", 0, Pins("A11 A18 D15 C7 V10 B7 F4 H2"), IOStandard("LVCMOS33")), - ("dac_sck", 0, Pins("D12 K16 C15 E7 V11 E6 F3 G2"), IOStandard("LVCMOS33")), - ("adc_conv", 0, Pins("V15 T11 N15 U18 U11 R10 R16 U17"), IOStandard("LVCMOS33")), - ("adc_sck", 0, Pins("U16 R12 M16 R17 V16 R11 N16 T18"), IOStandard("LVCMOS33")), - ("adc_sdo", 0, Pins("P14 T14 V17 P17 M13 R13 N14 R18"), IOStandard("LVCMOS33")), +# ("differntial_output_low", 0, Pins("J17 J18 K15 J15 U14 V14 T13 U13 B6 E5 A3"), IOStandard("LVCMOS33")), + ("dac_ss_L_0", 0, Pins("G13"), IOStandard("LVCMOS33")), + ("dac_mosi_0", 0, Pins("B11"), IOStandard("LVCMOS33")), + ("dac_miso_0", 0, Pins("A11"), IOStandard("LVCMOS33")), + ("dac_sck_0", 0, Pins("D12"), IOStandard("LVCMOS33")), +# ("dac_ss_L", 0, Pins("G13 D13 E15 F5 U12 D7 D4 E2"), IOStandard("LVCMOS33")), +# ("dac_mosi", 0, Pins("B11 B18 E16 D8 V12 D5 D3 D2"), IOStandard("LVCMOS33")), +# ("dac_miso", 0, Pins("A11 A18 D15 C7 V10 B7 F4 H2"), IOStandard("LVCMOS33")), +# ("dac_sck", 0, Pins("D12 K16 C15 E7 V11 E6 F3 G2"), IOStandard("LVCMOS33")), +# ("adc_conv", 0, Pins("V15 T11 N15 U18 U11 R10 R16 U17"), IOStandard("LVCMOS33")), +# ("adc_sck", 0, Pins("U16 R12 M16 R17 V16 R11 N16 T18"), IOStandard("LVCMOS33")), +# ("adc_sdo", 0, Pins("P14 T14 V17 P17 M13 R13 N14 R18"), IOStandard("LVCMOS33")), ("module_reset", 0, Pins("D9"), IOStandard("LVCMOS33")), - ("test_clock", 0, Pins("P18"), IOStandard("LVCMOS33")) +# ("test_clock", 0, Pins("P18"), IOStandard("LVCMOS33")) ] -class PreemptiveInterface(Module, AutoCSR): - """ A preemptive interface is a manually controlled Wishbone interface - that stands between multiple masters (potentially interconnects) and a - single slave. A master controls which master (or interconnect) has access - to the slave. This is to avoid bus contention by having multiple buses. """ - - def __init__(self, masters_len, slave): - """ - :param masters_len: The amount of buses accessing this slave. This number - must be greater than one. - :param slave: The slave device. This object must have an Interface object - accessable as ``bus``. - """ - - assert masters_len > 1 - self.buses = [] - self.master_select = CSRStorage(masters_len, name='master_select', description='RW bitstring of which master interconnect to connect to') - self.slave = slave - - for i in range(masters_len): - # Add the slave interface each master interconnect sees. - self.buses.append(Interface(data_width=32, address_width=32, addressing="byte")) - self.comb += [ - self.buses[i].cti.eq(0), - self.buses[i].bte.eq(0), - ] - - """ - Construct a combinatorial case statement. In verilog, the if - statment would look like - - always @ (*) case (master_select) - 1: begin - // Bus assignments... - end - 2: begin - // Bus assignments... - end - // more cases: - default: - // assign everything to master 0 - end - - The If statement in Migen (Python HDL) is an object with a method - called "ElseIf" and "Else", that return objects with the specified - case attached. Instead of directly writing an If statement into - the combinatorial block, the If statement is constructed in a - for loop. - - The "assign_for_case" function constructs the body of the If - statement. It assigns all output ports to avoid latches. - """ - - def assign_for_case(i): - asn = [ ] - - for j in range(masters_len): - asn += [ - self.buses[i].cyc.eq(self.slave.bus.cyc if i == j else 0), - self.buses[i].stb.eq(self.slave.bus.stb if i == j else 0), - self.buses[i].we.eq(self.slave.bus.we if i == j else 0), - self.buses[i].sel.eq(self.slave.bus.sel if i == j else 0), - self.buses[i].adr.eq(self.slave.bus.adr if i == j else 0), - self.buses[i].dat_w.eq(self.slave.bus.dat_w if i == j else 0), - self.buses[i].ack.eq(self.slave.bus.ack if i == j else 0), - self.buses[i].dat_r.eq(self.slave.bus.dat_r if i == j else 0), - self.buses[i].cti.eq(0), - self.buses[i].bte.eq(0), - ] - return asn - - cases = {"default": assign_for_case(0)} - for i in range(1, masters_len): - cases[i] = assign_for_case(i) - - self.comb += Case(self.master_select.storage, cases) +# class PreemptiveInterface(Module, AutoCSR): +# """ A preemptive interface is a manually controlled Wishbone interface +# that stands between multiple masters (potentially interconnects) and a +# single slave. A master controls which master (or interconnect) has access +# to the slave. This is to avoid bus contention by having multiple buses. """ +# +# def __init__(self, masters_len, slave): +# """ +# :param masters_len: The amount of buses accessing this slave. This number +# must be greater than one. +# :param slave: The slave device. This object must have an Interface object +# accessable as ``bus``. +# """ +# +# assert masters_len > 1 +# self.buses = [] +# self.master_select = CSRStorage(masters_len, name='master_select', description='RW bitstring of which master interconnect to connect to') +# self.slave = slave +# +# for i in range(masters_len): +# # Add the slave interface each master interconnect sees. +# self.buses.append(Interface(data_width=32, address_width=32, addressing="byte")) +# +# """ +# Construct a combinatorial case statement. In verilog, the if +# statment would look like +# +# always @ (*) case (master_select) +# 1: begin +# // Bus assignments... +# end +# 2: begin +# // Bus assignments... +# end +# // more cases: +# default: +# // assign everything to master 0 +# end +# +# The If statement in Migen (Python HDL) is an object with a method +# called "ElseIf" and "Else", that return objects with the specified +# case attached. Instead of directly writing an If statement into +# the combinatorial block, the If statement is constructed in a +# for loop. +# +# The "assign_for_case" function constructs the body of the If +# statement. It assigns all output ports to avoid latches. +# """ +# +# def assign_for_case(i): +# asn = [ ] +# +# for j in range(masters_len): +# asn += [ +# self.buses[i].cyc.eq(self.slave.bus.cyc if i == j else 0), +# self.buses[i].stb.eq(self.slave.bus.stb if i == j else 0), +# self.buses[i].we.eq(self.slave.bus.we if i == j else 0), +# self.buses[i].sel.eq(self.slave.bus.sel if i == j else 0), +# self.buses[i].adr.eq(self.slave.bus.adr if i == j else 0), +# self.buses[i].dat_w.eq(self.slave.bus.dat_w if i == j else 0), +# self.buses[i].ack.eq(self.slave.bus.ack if i == j else 0), +# self.buses[i].dat_r.eq(self.slave.bus.dat_r if i == j else 0), +# ] +# return asn +# +# cases = {"default": assign_for_case(0)} +# for i in range(1, masters_len): +# cases[i] = assign_for_case(i) +# +# self.comb += Case(self.master_select.storage, cases) class SPIMaster(Module): def __init__(self, rst, miso, mosi, sck, ss, - polarity = 0, - phase = 0, - ss_wait = 1, - enable_miso = 1, - enable_mosi = 1, - spi_wid = 24, - spi_cycle_half_wait = 1, + polarity = 0, + phase = 0, + ss_wait = 1, + enable_miso = 1, + enable_mosi = 1, + spi_wid = 24, + spi_cycle_half_wait = 1, ): - self.bus = Interface(data_width = 32, address_width=32, addressing="word") - self.region = SoCIORegion(size=0x10, cached=False) + self.bus = Interface(data_width = 32, address_width=32, addressing="byte") + self.region = SoCRegion(size=0x10, cached=False) + self.comb += [ - self.bus.cti.eq(0), - self.bus.bte.eq(0), + self.bus.err.eq(0), ] self.specials += Instance("spi_master_ss_wb", - SS_WAIT = ss_wait, - SS_WAIT_TIMER_LEN = minwid(ss_wait), - CYCLE_HALF_WAIT = spi_cycle_half_wait, - TIMER_LEN = minwid(spi_cycle_half_wait), - WID = spi_wid, - WID_LEN = minwid(spi_wid), - ENABLE_MISO = enable_miso, - ENABLE_MOSI = enable_mosi, - POLARITY = polarity, - PHASE = phase, + p_SS_WAIT = ss_wait, + p_SS_WAIT_TIMER_LEN = minbits(ss_wait), + p_CYCLE_HALF_WAIT = spi_cycle_half_wait, + p_TIMER_LEN = minbits(spi_cycle_half_wait), + p_WID = spi_wid, + p_WID_LEN = minbits(spi_wid), + p_ENABLE_MISO = enable_miso, + p_ENABLE_MOSI = enable_mosi, + p_POLARITY = polarity, + p_PHASE = phase, i_clk = ClockSignal(), i_rst_L = rst, @@ -229,158 +227,150 @@ class SPIMaster(Module): ) # TODO: Generalize CSR stuff -class ControlLoopParameters(Module, AutoCSR): - def __init__(self): - self.cl_I = CSRStorage(32, description='Integral parameter') - self.cl_P = CSRStorage(32, description='Proportional parameter') - self.deltaT = CSRStorage(32, description='Wait parameter') - self.setpt = CSRStorage(32, description='Setpoint') - self.zset = CSRStatus(32, description='Set Z position') - self.zpos = CSRStatus(32, description='Measured Z position') - - self.bus = Interface(data_width = 32, address_width = 32, addressing="word") - self.region = SoCRegion(size=minbits(0x17), cached=False) - self.comb += [ - self.bus.cti.eq(0), - self.bus.bte.eq(0), - ] - self.sync += [ - If(self.bus.cyc == 1 and self.bus.stb == 1 and self.bus.ack == 0, - Case(self.bus.adr[0:4], { - 0x0: self.bus.dat_r.eq(self.cl_I.storage), - 0x4: self.bus.dat_r.eq(self.cl_P.storage), - 0x8: self.bus.dat_r.eq(self.deltaT.storage), - 0xC: self.bus.dat_r.eq(self.setpt.storage), - 0x10: If(self.bus.we, - self.zset.status.eq(self.bus.dat_w) - ).Else( - self.bus.dat_r.eq(self.zset.status) - ), - 0x14: If(self.bus.we, - self.zpos.status.eq(self.bus.dat_w), - ).Else( - self.bus.dat_r.eq(self.zpos.status) - ), - }), - self.bus.ack.eq(1), - ).Else( - self.bus.ack.eq(0), - ) - ] - -class BRAM(Module): - """ A BRAM (block ram) is a memory store that is completely separate from - the system RAM. They are much smaller. - """ - def __init__(self, addr_mask, origin=None): - """ - :param addr_mask: Mask which defines the amount of bytes accessable - by the BRAM. - :param origin: Origin of the BRAM module region. This is seen by the - subordinate master, not the usual master. - """ - self.bus = Interface(data_width=32, address_width=32, addressing="byte") - - # Non-IO (i.e. MMIO) regions need to be cached - self.region = SoCRegion(origin=origin, size=addr_mask+1, cached=True) - - self.comb += [ - self.bus.cti.eq(0), - self.bus.bte.eq(0), - ] - self.specials += Instance("bram", - p_ADDR_MASK = addr_mask, - i_clk = ClockSignal(), - i_wb_cyc = self.bus.cyc, - i_wb_stb = self.bus.stb, - i_wb_we = self.bus.we, - i_wb_sel = self.bus.sel, - i_wb_addr = self.bus.adr, - i_wb_dat_w = self.bus.dat_w, - o_wb_ack = self.bus.ack, - o_wb_dat_r = self.bus.dat_r, - ) - -class PicoRV32(Module, AutoCSR): - def __init__(self, bramwid=0x1000): - self.submodules.params = params = ControlLoopParameters() - self.submodules.bram = self.bram = bram = BRAM(bramwid-1, origin=0x10000) - self.submodules.bram_iface = self.bram_iface = bram_iface = PreemptiveInterface(2, bram) - - # This is the PicoRV32 master - self.masterbus = Interface(data_width=32, address_width=32, addressing="byte") - - self.resetpin = CSRStorage(1, name="picorv32_reset", description="PicoRV32 reset") - self.trap = CSRStatus(1, name="picorv32_trap", description="Trap bit") - - self.ic = ic = SoCBusHandler( - standard="wishbone", - data_width=32, - address_width=32, - timeout=1e6, - bursting=False, - interconnect="shared", - interconnect_register=True, - reserved_regions={ - "picorv32_null_region": SoCRegion(origin=0,size=0x10000, mode="ro", cached=True), - "picorv32_io": SoCIORegion(origin=0x100000, size=0x100, mode="rw", cached=False), - }, - ) - - ic.add_slave("picorv32_bram", bram_iface.buses[1], bram.region) - ic.add_slave("picorv32_params", params.bus, params.region) - ic.add_master("picorv32_master", self.masterbus) - - # NOTE: need to compile to these extact instructions - self.specials += Instance("picorv32_wb", - p_COMPRESSED_ISA = 1, - p_ENABLE_MUL = 1, - p_PROGADDR_RESET=0x10000, - p_PROGADDR_IRQ=0x100010, - p_REGS_INIT_ZERO = 1, - o_trap = self.trap.status, - - i_wb_rst_i = ~self.resetpin.storage, - i_wb_clk_i = ClockSignal(), - o_wbm_adr_o = self.masterbus.adr, - o_wbm_dat_o = self.masterbus.dat_r, - i_wbm_dat_i = self.masterbus.dat_w, - o_wbm_we_o = self.masterbus.we, - o_wbm_sel_o = self.masterbus.sel, - o_wbm_stb_o = self.masterbus.stb, - i_wbm_ack_i = self.masterbus.ack, - o_wbm_cyc_o = self.masterbus.cyc, - - o_pcpi_valid = Signal(), - o_pcpi_insn = Signal(32), - o_pcpi_rs1 = Signal(32), - o_pcpi_rs2 = Signal(32), - i_pcpi_wr = 0, - i_pcpi_wait = 0, - i_pcpi_rd = 0, - i_pcpi_ready = 0, - - i_irq = 0, - o_eoi = Signal(32), - - o_trace_valid = Signal(), - o_trace_data = Signal(36), - ) - - def do_finalize(self): - self.ic.finalize() - jsondata = {} - - for region in self.ic.regions: - d = self.ic.regions[region] - jsondata[region] = { - "origin": d.origin, - "size": d.size, - } - - with open('picorv32.json', 'w') as f: - import json - json.dump(jsondata, f) +# class ControlLoopParameters(Module, AutoCSR): +# def __init__(self): +# self.cl_I = CSRStorage(32, description='Integral parameter') +# self.cl_P = CSRStorage(32, description='Proportional parameter') +# self.deltaT = CSRStorage(32, description='Wait parameter') +# self.setpt = CSRStorage(32, description='Setpoint') +# self.zset = CSRStatus(32, description='Set Z position') +# self.zpos = CSRStatus(32, description='Measured Z position') +# +# self.bus = Interface(data_width = 32, address_width = 32, addressing="word") +# self.region = SoCRegion(size=minbits(0x17), cached=False) +# self.sync += [ +# If(self.bus.cyc == 1 and self.bus.stb == 1 and self.bus.ack == 0, +# Case(self.bus.adr[0:4], { +# 0x0: self.bus.dat_r.eq(self.cl_I.storage), +# 0x4: self.bus.dat_r.eq(self.cl_P.storage), +# 0x8: self.bus.dat_r.eq(self.deltaT.storage), +# 0xC: self.bus.dat_r.eq(self.setpt.storage), +# 0x10: If(self.bus.we, +# self.zset.status.eq(self.bus.dat_w) +# ).Else( +# self.bus.dat_r.eq(self.zset.status) +# ), +# 0x14: If(self.bus.we, +# self.zpos.status.eq(self.bus.dat_w), +# ).Else( +# self.bus.dat_r.eq(self.zpos.status) +# ), +# }), +# self.bus.ack.eq(1), +# ).Else( +# self.bus.ack.eq(0), +# ) +# ] +# +# class BRAM(Module): +# """ A BRAM (block ram) is a memory store that is completely separate from +# the system RAM. They are much smaller. +# """ +# def __init__(self, addr_mask, origin=None): +# """ +# :param addr_mask: Mask which defines the amount of bytes accessable +# by the BRAM. +# :param origin: Origin of the BRAM module region. This is seen by the +# subordinate master, not the usual master. +# """ +# self.bus = Interface(data_width=32, address_width=32, addressing="byte") +# +# # Non-IO (i.e. MMIO) regions need to be cached +# self.region = SoCRegion(origin=origin, size=addr_mask+1, cached=True) +# +# self.specials += Instance("bram", +# p_ADDR_MASK = addr_mask, +# i_clk = ClockSignal(), +# i_wb_cyc = self.bus.cyc, +# i_wb_stb = self.bus.stb, +# i_wb_we = self.bus.we, +# i_wb_sel = self.bus.sel, +# i_wb_addr = self.bus.adr, +# i_wb_dat_w = self.bus.dat_w, +# o_wb_ack = self.bus.ack, +# o_wb_dat_r = self.bus.dat_r, +# ) +# +# class PicoRV32(Module, AutoCSR): +# def __init__(self, bramwid=0x1000): +# self.submodules.params = params = ControlLoopParameters() +# self.submodules.bram = self.bram = bram = BRAM(bramwid-1, origin=0x10000) +# self.submodules.bram_iface = self.bram_iface = bram_iface = PreemptiveInterface(2, bram) +# +# # This is the PicoRV32 master +# self.masterbus = Interface(data_width=32, address_width=32, addressing="byte") +# +# self.resetpin = CSRStorage(1, name="picorv32_reset", description="PicoRV32 reset") +# self.trap = CSRStatus(1, name="picorv32_trap", description="Trap bit") +# +# self.ic = ic = SoCBusHandler( +# standard="wishbone", +# data_width=32, +# address_width=32, +# timeout=1e6, +# bursting=False, +# interconnect="shared", +# interconnect_register=True, +# reserved_regions={ +# "picorv32_null_region": SoCRegion(origin=0,size=0x10000, mode="ro", cached=True), +# "picorv32_io": SoCIORegion(origin=0x100000, size=0x100, mode="rw", cached=False), +# }, +# ) +# +# ic.add_slave("picorv32_bram", bram_iface.buses[1], bram.region) +# ic.add_slave("picorv32_params", params.bus, params.region) +# ic.add_master("picorv32_master", self.masterbus) +# +# # NOTE: need to compile to these extact instructions +# self.specials += Instance("picorv32_wb", +# p_COMPRESSED_ISA = 1, +# p_ENABLE_MUL = 1, +# p_PROGADDR_RESET=0x10000, +# p_PROGADDR_IRQ=0x100010, +# p_REGS_INIT_ZERO = 1, +# o_trap = self.trap.status, +# +# i_wb_rst_i = ~self.resetpin.storage, +# i_wb_clk_i = ClockSignal(), +# o_wbm_adr_o = self.masterbus.adr, +# o_wbm_dat_o = self.masterbus.dat_r, +# i_wbm_dat_i = self.masterbus.dat_w, +# o_wbm_we_o = self.masterbus.we, +# o_wbm_sel_o = self.masterbus.sel, +# o_wbm_stb_o = self.masterbus.stb, +# i_wbm_ack_i = self.masterbus.ack, +# o_wbm_cyc_o = self.masterbus.cyc, +# +# o_pcpi_valid = Signal(), +# o_pcpi_insn = Signal(32), +# o_pcpi_rs1 = Signal(32), +# o_pcpi_rs2 = Signal(32), +# i_pcpi_wr = 0, +# i_pcpi_wait = 0, +# i_pcpi_rd = 0, +# i_pcpi_ready = 0, +# +# i_irq = 0, +# o_eoi = Signal(32), +# +# o_trace_valid = Signal(), +# o_trace_data = Signal(36), +# ) +# +# def do_finalize(self): +# self.ic.finalize() +# jsondata = {} +# +# for region in self.ic.regions: +# d = self.ic.regions[region] +# jsondata[region] = { +# "origin": d.origin, +# "size": d.size, +# } +# +# with open('picorv32.json', 'w') as f: +# import json +# json.dump(jsondata, f) # Clock and Reset Generator # I don't know how this works, I only know that it does. @@ -423,7 +413,11 @@ class UpsilonSoC(SoCCore): def add_picorv32(self): self.submodules.picorv32 = pr = PicoRV32() self.bus.add_slave("picorv32_master_bram", pr.bram_iface.buses[0], - SoCRegion(size=pr.bram.region.size, cached=True)) + SoCRegion(origin=None,size=pr.bram.region.size, cached=True)) + + def add_bram(self): + self.submodules.bram = br = BRAM(0x1FF) + self.bus.add_slave("bram", br.bus, br.region) def __init__(self, variant="a7-100", @@ -456,7 +450,7 @@ class UpsilonSoC(SoCCore): # SoCCore does not have sane defaults (no integrated rom) SoCCore.__init__(self, clk_freq=sys_clk_freq, - toolchain="f4pga", + toolchain="symbiflow", platform = platform, bus_standard = "wishbone", ident = f"Arty-{variant} F4PGA LiteX VexRiscV Zephyr - Upsilon", @@ -500,6 +494,16 @@ class UpsilonSoC(SoCCore): # Add pins platform.add_extension(io) + self.submodules.spi0 = SPIMaster( + platform.request("module_reset"), + platform.request("dac_miso_0"), + platform.request("dac_mosi_0"), + platform.request("dac_sck_0"), + platform.request("dac_ss_L_0"), + ) + self.bus.add_slave("spi0", self.spi0.bus, self.spi0.region) + + #self.add_bram() #self.add_picorv32() def main():