
Разработчики FPGA часто сталкиваются с необходимостью внедрения в свой проект софт процессора. Когда-то давно мы могли использовать проприетарные Altera NIOS или Xilinx MicroBlase. Но время идет. В последние годы наблюдается устойчивый тренд перехода производителей ПЛИС в сторону поддержки архитектуры RISC-V.
RISC-V это открытая, расширяемая и бесплатная архитектура набора команд (ISA), которая не требует лицензионных отчислений. Оба FPGA вендора Altera и Xilinx уже довольно давно предлагают и активно разрабатывают поддержку RISC-V в своих новых продуктах, теперь это уже софт процессоры NIOS V и MicroBlase V для FPGA.
Однако, зачем использовать всё ещё проприетарные ядра, если можно использовать Open Source?
В этой статье я сравниваю два Open Source RISC-V микропроцессора:
1) picorv32 от компании YoSys (https://github.com/YosysHQ/picorv32) и
2) scr1 от Syntacore (https://github.com/syntacore/scr1)
Что буду сравнивать? Производительность софт ядер и занимаемые ресурсы в ПЛИС.
Как правильно сравнить? Использовать единую тестовую программу написанную на языке C, например Dhrystone, и скомпилированную в бинарный файл, или HEX файл и запускаемую в двух архитектурно одинаковых SOC, но с разными ядрами RISC-V.
Интересно, что в исходниках picorv32 есть тест Dhrystone и в исходниках scr1 есть тест Dhrystone, но у них хоть и похожие, но всё же разные файлы по содержимому! Кроме этого, разработчики этих ядер ссылаются на разные тулчейны для сборки. Согласитесь, что не совсем верно собирать единую прошивку разными компиляторами. Для чистоты эксперимента я буду использовать один компилятор взятый вот отсюда: https://syntacore.com/tools/development-tools У меня получится одна «прошивка» для двух разных SOC и тогда это будет самое объективное сравнение.
Еще одно замечание: RISC-V архитектура подразумевает конфигурируемость. Если мало ресурсов в ПЛИС, то можно использовать урезанную версию процессора и у него будет к примеру не 32 регистра общего назначения, а только 16. Или можно сделать версию процессора без умножителя. Вариантов конфигураций процессора может быть довольно много, но чтобы сильно не заморачиваться я остановился на двух конфигурациях:
-
минимальная, 16 регистров, без аппаратного умножителя, но с поддержкой сжатых инструкций
-
максимальная, 32 регистра, с умножителем, с поддержкой сжатых инструкций.
Таким образом, мои тесты коснутся двух разных ядер в двух разных конфигурациях.
Запускать эти SOC я буду на платах Марсоход3 с чипом FPGA MAX10 50K логических элементов и на плате Марсоход3бис с чипом FPGA MAX10 8K логических элементов.
Кроме этого, я буду запускать тестбенчи для всех этих четырех случаев.
Исходники моего проекта для сравнения ядер находятся на github https://github.com/marsohod4you/riscv-compare Учтите, что этот проект включает в себя субмодули git для каждого из ядер scr1 и picorv32.
Ключевые особенности проекта PicoRV32, YosysHQ
PicoRV32 — это компактное и гибкое ядро процессора, реализующее архитектуру RISC-V (RV32IMC) и предназначенное для использования в FPGA и ASIC. Основные особенности:
-
Оптимизация по размеру и частоте.
-
Гибкая конфигурация: поддерживает разные варианты системы команд — RV32E, RV32I, RV32IC, RV32IM, RV32IMC.
-
Можно отключать регистры x16…x31, инструкции RDCYCLE[H], RDTIME[H], RDINSTRET[H], что уменьшает размер ядра.
-
Интерфейсы: доступны три варианта ядра с разными шинами — простой native-интерфейс, AXI4-Lite (picorv32_axi) и Wishbone (picorv32_wb), что облегчает интеграцию в различные системы.
Опциональные возможности:
-
Встроенный контроллер прерываний IRQ.
-
Интерфейс сопроцессора (PCPI) для расширения системы команд.
-
Поддержка аппаратных умножителя/делителя и barrel-shifter.
-
Возможность выбора между одно- и двухпортовой организацией регистрового файла для баланса между скоростью и размером.
-
Тестирование и поддержка: в проекте есть множество тестбенчей, примеры SoC, готовые прошивки и скрипты для сборки и симуляции (Icarus Verilog, GtkWave), а также подробные инструкции по сборке и запуску на различных платах.
-
Лицензия: ядро распространяется по лицензии ISC (аналог MIT/BSD), что позволяет свободное использование в коммерческих и открытых проектах.
Применение: хорошо подходит как вспомогательный процессор в FPGA/ASIC, для образовательных целей, прототипирования SoC и встраиваемых решений.
Предполагаемое использование микропроцессора в FPGA совместно с внешней SPI Flash памятью, где хранится программа. Встроенная в SOC статическая память, по умолчанию всего 1 килобайт служит кэшем / scratchpad для внешней flash памяти. Таким образом не нужно заботиться о минимизации размера кода пользовательских программ.
Вот типовая блок схема SOC, которую рекомендует YosysHQ:
В своём же проекте для сравнения характеристик picorv32 и scr1 я буду делать совсем не так, а гораздо проще. У меня не будет внешней флэш памяти, а всю тестовую программу Dhrystone я размещу в статической памяти ПЛИС 32 килобайта в адресном пространстве микропроцессора по адресу ноль. При включении процессора он будет сразу читать и исполнять команды с адреса ноль. Никаких прерываний я не буду использовать. Вот такая будет моя простая система на кристалле:
В моей простейшей SOC на основе picorv32 будет только процессор, и на шине данных статическая память программ и данных, последовательный порт, регистр 7ми сегментного индикатора и регистр на запись используемый во время симуляции. Когда программа запишет в этот регистр что ни будь — симулятор остановит свою работу.
На семи-сегментном индикаторе я буду отображать результат измерения производительности в Dhrystone.
Ключевые особенности проекта SCR1
Syntacore SCR1 — это высококачественное открытое ядро микроконтроллера, совместимое с архитектурой RISC-V, разработанное и поддерживаемое компанией Syntacore, сейчас Yadro. Основные особенности проекта:
-
Открытая лицензия: ядро распространяется по лицензии SHL, что позволяет неограниченное коммерческое использование, что редко встречается среди ядер, поддерживаемых коммерческими компаниями.
-
Поддержка архитектурных расширений: реализует базовый набор команд RV32I или RV32E с возможностью подключения расширений RVM (умножение/деление) и RVC (сжатые инструкции).
-
Режимы привилегий: поддерживает только машинный режим привилегий (Machine mode), что характерно для микроконтроллерных ядер.
-
Конвейер: 2–4 стадии, в зависимости от конфигурации, что позволяет балансировать между производительностью и площадью.
-
Интерфейсы: 32-битный внешний интерфейс AXI4 или AHB-Lite для интеграции с периферией и памятью.
-
Интегрированный программируемый контроллер прерываний (до 16 линий IRQ);
-
Отладочная подсистема с интерфейсом JTAG;
-
Опциональная тесно связанная память (TCM) для ускорения доступа к критичным данным.
-
Язык описания: написан на SystemVerilog, что обеспечивает хорошую переносимость и поддержку в современных EDA-средах.
-
Оптимизация: ядро оптимизировано по площади и энергопотреблению, подходит для MCU-класса и встраиваемых решений.
-
Гибкая конфигурация: доступны три предопределённые конфигурации (MAX, BASE, MIN), а также множество параметров для тонкой настройки под конкретные задачи.
-
Верификация и документация: проект сопровождается обширной документацией, тестовыми наборами (включая тесты на соответствие RISC-V ISA, Dhrystone, CoreMark), а также примерами для быстрого старта.
-
Поддержка симуляторов и платформ: совместим с основными промышленными симуляторами (Verilator, ModelSim, VCS, NCSim),
-
Поддерживается сборка и запуск на популярных отладочных платах (Arty, Nexys 4 DDR, DE10-Lite и др.).
-
Экосистема: к ядру прилагается SDK с загрузчиком, поддержкой Zephyr RTOS, примерами программного обеспечения и руководствами пользователя. SCR1 — одно из самых популярных открытых ядер RISC-V для микроконтроллеров, широко используемое как в образовательных, так и в коммерческих проектах.
Российский RISC-V микроконтроллер Амур кажется использует очень похожее ядро, возможно это же самое (но это не точно).
Свою SOC на основе SCR1 я так же делаю минимально возможной. В процессоре уже есть встроенная TCM (Tightly Coupled Memory) память. С помощью кастомной конфигурации проекта я устанавливаю её размер в 32К и размещаю её по адресу ноль. Мой процессор так же будет стартовать с адреса ноль прямо в TCM. Прерывания я не использую. На внешней шине ставлю по тем же адресам последовательный порт, регистр семи-сегментного индикатора и регистр останова при симуляции:
Таким образом, архитектурно обе проектируемые мною SOC будут идентичными:
// 8K 32bit words = 32Kbytes memory localparam MEM_SIZE = (1024*32); //at address zero localparam SERIAL_PORT_ADDR = 32’h1000_0000; localparam SEG7_PORT_ADDR = 32’h1000_0004; localparam SIMSTOP_PORT_ADDR = 32’h1000_1000;
Компилируем программу Dhrystone
Склонируйте мой проект с github вместе с субмодулями:
git clone —recurse-submodules https://github.com/marsohod4you/riscv-compare.git
Перейдите в директорию Си проекта:
cd riscv-compare/dhrystone-fw/
Возможно вам потребуется исправить в скрипте build.sh строку export PATH=$PATH: и добавить туда именно ваши пути к тулчейну risc-v и к питону. Напомню, что я использую тулчейн взятый вот здесь: https://syntacore.com/tools/development-tools
Запустите скрипт build.sh с параметром EC или IM. Эти параметры как раз будут определять какой код генерировать. EC это для процессора с минимальной конфигурацией, embedded, компилятор gcc будет использовать только 16 регистров, не будет использовать операции умножения, но будет использовать сжатый код. Сжатый код позволяет использовать короткие 16ти битные команды процессора если это возможно. Это позволяет экономить место программы. При этом 32х битные инструкции конечно всё еще доступны.
Если задать параметр IM, то скрипт будет генерировать код с учетом наличия 32х регистров и используя команды умножения если нужно.
Компилирую скриптом:
./build.sh IM
./build.sh EC
После компиляции появятся новые директории riscv-compare/dhrystone/done_ec и riscv-compare/dhrystone/done_im. В них результирующие файлы и вы можете поизучать их. В файле dhry.dump например можно посмотреть ассемблерный код полученный в результате сборки. Обратите внимание, что в файле riscv-compare/dhrystone/done_im/dhry.dump вы найдёте гораздо большее число используемых регистров. Кроме того, там будет использование команд типа mulhu, а в EC дампе вместо этого вы встретите вызов подпрограмм типа jal <__mulsi3>.
Файлы используемые для симуляции и для сборки FPGA проекта это обычно *.hex. Эти файлы так же создаются.
Этот же скрипт скопирует результирующие файлы куда нужно и для симуляции и для проектов Quartus Prime для компиляции FPGA проектов.
Симуляция работы SOC с RISC-V ядрами.
Симулировать проект picorv32 SOC очень просто даже с помощью Icarus Verilog — но он должен быть заранее установлен у вас. Это возможно потому, что всё ядро описано на Verilog HDL. И всё ядро это один файл picorv32.v.
Перейдите в папку riscv-compare/FPGA/m3-picorv32/sim и запустите скрипт симулятора опять же с параметром EC или IM:
cd ./riscv-compare/FPGA/m3-picorv32/sim ./simulate.sh IM
Этот скрипт и компилирует и симулирует. В результате вы сможете увидеть вот такой вывод:
$ ./simulate.sh IMSimulate for CPU with mul/dev and 32 regsFirmware Boot File exists: dhry_im.hexSimulation with FW Boot File for CPU with MUL/DIV instructions number of REGs=32Simulation Config for CPU with MUL/DIV and number of REGs=32VCD info: dumpfile testbench.vcd opened for output.STARTDhrystone Benchmark, Version 2.1 (Language: C)Program compiled without 'register' attributeExecution starts, 500 runs through DhrystoneExecution endsFinal values of the variables used in the benchmark:Int_Glob: 5 should be: 5Bool_Glob: 1 should be: 1Ch_1_Glob: A should be: ACh_2_Glob: B should be: BArr_1_Glob[8]: 7 should be: 7Arr_2_Glob[8][7]: 510 should be: Number_Of_Runs + 10Ptr_Glob-> Ptr_Comp: 12540 should be: (implementation-dependent) Discr: 0 should be: 0 Enum_Comp: 2 should be: 2 Int_Comp: 17 should be: 17 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRINGNext_Ptr_Glob-> Ptr_Comp: 12540 should be: (implementation-dependent), same as above Discr: 0 should be: 0 Enum_Comp: 1 should be: 1 Int_Comp: 18 should be: 18 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRINGInt_1_Loc: 5 should be: 5Int_2_Loc: 13 should be: 13Int_3_Loc: 7 should be: 7Enum_Loc: 1 should be: 1Str_1_Loc: DHRYSTONE PROGRAM, 1'ST STRING should be: DHRYSTONE PROGRAM, 1'ST STRINGStr_2_Loc: DHRYSTONE PROGRAM, 2'ND STRING should be: DHRYSTONE PROGRAM, 2'ND STRINGBeginTime 57844 EndTime 789033 UserTime 731189Number_Of_Runs= 500, HZ= 1000000Time: begin= 57844, end= 789033, diff= 731189Microseconds for one run through Dhrystone: 1462Dhrystones per Second: 683Cycles_Per_Instruction: 5.623Seg4x7 register Written 00000683DONE../soc.v:135: $finish called at 963340000000 (1ps)
Если есть желание, можно детально рассмотреть все сигналы в проекте с помощью gtkwave и сгенерированного testbench.vcd файла.
Симулировать scr1 проект не так просто. Scr1 написан на SystemVerilog и Icarus его почти не поддерживает. Здесь нужен Verilator. Проще всего его конечно установить и использовать в среде Linux.
Я так же приготовил скрипт для симуляции.
Перейдите в директорию riscv-compare/FPGA/m3-scr1/sim и запустите скрипт симуляции
cd ./riscv-compare/FPGA/m3-scr1/sim ./simulate.sh IM
Скрипт последовательно и компилирует и симулирует используя Verilator. Вывод скрипта содержит вот такой длинный текст:
Скрытый текст
Simulate for CPU with mul/dev and 32 regsFirmware Boot File exists: dhry32_im.hex****************************************************** Patching SCR1 project.. ******************************************************Patching SCR1 project done..****************************************************** Compile with Verilator.. ******************************************************rm: cannot remove ‘obj_dir’: Is a directory%Warning-TIMESCALEMOD: ../../m3-scr1/max10.v:4:8: Timescale missing on this module as other modules have it (IEEE 1800-2023 3.14.2.3) 4 | module max10( | ^~~~~ ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:123:8: … Location of module with timescale 123 | module generic_fifo_dc_gray( rd_clk, wr_clk, rst, clr, din, we, | ^~~~~~~~~~~~~~~~~~~~ … For warning description see https://verilator.org/warn/TIMESCALEMOD?v=5.037 … Use «/* verilator lint_off TIMESCALEMOD /» and lint_on around source to disable this message.%Warning-TIMESCALEMOD: ../../common/sserial.v:3:8: Timescale missing on this module as other modules have it (IEEE 1800-2023 3.14.2.3) 3 | module sserial( | ^~~~~~~ ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:123:8: … Location of module with timescale 123 | module generic_fifo_dc_gray( rd_clk, wr_clk, rst, clr, din, we, | ^~~~~~~~~~~~~~~~~~~~%Warning-TIMESCALEMOD: ../../common/generic_fifos/rtl/verilog/generic_dpram.v:99:8: Timescale missing on this module as other modules have it (IEEE 1800-2023 3.14.2.3) 99 | module generic_dpram( | ^~~~~~~~~~~~~ ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:123:8: … Location of module with timescale 123 | module generic_fifo_dc_gray( rd_clk, wr_clk, rst, clr, din, we, | ^~~~~~~~~~~~~~~~~~~~%Warning-TIMESCALEMOD: ../../../FPGA/m3-scr1/seg4x7.v:1:8: Timescale missing on this module as other modules have it (IEEE 1800-2023 3.14.2.3) 1 | module seg4x7( | ^~~~~~ ../../m3-scr1/max10.v:197:1: … note: In file included from ‘max10.v’ ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:123:8: … Location of module with timescale 123 | module generic_fifo_dc_gray( rd_clk, wr_clk, rst, clr, din, we, | ^~~~~~~~~~~~~~~~~~~~%Warning-IMPLICIT: ../../m3-scr1/max10.v:108:30: Signal definition not found, creating implicitly: ‘tdo’ : … Suggested alternative: ‘tdi’ 108 | .tdo (tdo ), | ^~~ … For warning description see https://verilator.org/warn/IMPLICIT?v=5.037 … Use «/ verilator lint_off IMPLICIT /» and lint_on around source to disable this message.%Warning-IMPLICIT: ../../m3-scr1/max10.v:109:30: Signal definition not found, creating implicitly: ‘tdo_en’ 109 | .tdo_en (tdo_en ), | ^~~~~~%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_hdu.svh:21:25: Operator VAR ‘SCR1_HDU_DEBUGCSR_ADDR_SPAN’ expects 32 bits on the Initial value, but Initial value’s VARREF ‘SCR1_CSR_ADDR_HDU_MSPAN’ generates 12 bits. : … note: In instance ‘max10’ 21 | localparam int unsigned SCR1_HDU_DEBUGCSR_ADDR_SPAN = SCR1_CSR_ADDR_HDU_MSPAN; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:17:1: … note: In file included from ‘scr1_pipe_top.sv‘ … For warning description see https://verilator.org/warn/WIDTHEXPAND?v=5.037 … Use «/ verilator lint_off WIDTHEXPAND /» and lint_on around source to disable this message.%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:70:41: Operator ADD expects 32 or 5 bits on the RHS, but RHS’s VARREF ‘SCR1_DBG_DMI_OP_WIDTH’ generates 2 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 70 | localparam DMI_OP_HI = DMI_OP_LO + SCR1_DBG_DMI_OP_WIDTH — 1; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_dm.svh:19:76: Operator ADD expects 6 bits on the LHS, but LHS’s VARREF ‘SCR1_DBG_DMI_OP_WIDTH’ generates 2 bits. : … note: In instance ‘max10’ 19 | parameter SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH = SCR1_DBG_DMI_OP_WIDTH + | ^ ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:11:1: … note: In file included from ‘scr1_tapc_synchronizer.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_hdu.svh:123:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_HDU_DBGCSR_OFFS_DPC’ generates 2 bits. : … note: In instance ‘max10’ 123 | localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DPC = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DPC; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:17:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_hdu.svh:124:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_HDU_DBGCSR_OFFS_DSCRATCH0’ generates 2 bits. : … note: In instance ‘max10’ 124 | localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DSCRATCH0 = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DSCRATCH0; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:17:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:120:65: Operator SHIFTL expects 32 bits on the LHS, but LHS’s VARREF ‘SCR1_MISA_MXL_32’ generates 2 bits. : … note: In instance ‘max10’ 120 | parameter bit [32-1:0] SCR1_CSR_MISA = (SCR1_MISA_MXL_32 << (32-2)) | ^~ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:84:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_CISV’ generates 3 bits. : … note: In instance ‘max10’ 84 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_CISV = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_CISV ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:85:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_CICSR’ generates 3 bits. : … note: In instance ‘max10’ 85 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_CICSR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_CICSR); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:86:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_IPR’ generates 3 bits. : … note: In instance ‘max10’ 86 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_IPR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_IPR ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:87:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_ISVR’ generates 3 bits. : … note: In instance ‘max10’ 87 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_ISVR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_ISVR ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:88:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_EOI’ generates 3 bits. : … note: In instance ‘max10’ 88 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_EOI = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_EOI ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:89:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_SOI’ generates 3 bits. : … note: In instance ‘max10’ 89 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_SOI = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_SOI ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:90:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_IDX’ generates 3 bits. : … note: In instance ‘max10’ 90 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_IDX = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_IDX ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_csr.svh:91:96: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_IPIC_ICSR’ generates 3 bits. : … note: In instance ‘max10’ 91 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_ICSR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_ICSR ); | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_tracelog.sv:9:1: … note: In file included from ‘scr1_tracelog.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_hdu.svh:122:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_HDU_DBGCSR_OFFS_DCSR’ generates 2 bits. : … note: In instance ‘max10’ 122 | localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DCSR = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DCSR; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:17:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_hdu.svh:125:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_HDU_DBGCSR_OFFS_DSCRATCH1’ generates 2 bits. : … note: In instance ‘max10’ 125 | localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DSCRATCH1 = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DSCRATCH1; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:17:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:36:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_CSR_ADDR_TDU_OFFS_TSELECT’ generates 3 bits. : … note: In instance ‘max10’ 36 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TSELECT = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TSELECT; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:37:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_CSR_ADDR_TDU_OFFS_TDATA1’ generates 3 bits. : … note: In instance ‘max10’ 37 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TDATA1 = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TDATA1; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:38:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_CSR_ADDR_TDU_OFFS_TDATA2’ generates 3 bits. : … note: In instance ‘max10’ 38 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TDATA2 = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TDATA2; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:39:99: Operator ADD expects 12 bits on the RHS, but RHS’s VARREF ‘SCR1_CSR_ADDR_TDU_OFFS_TINFO’ generates 3 bits. : … note: In instance ‘max10’ 39 | parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TINFO = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TINFO; | ^ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:72:25: Operator VAR ‘SCR1_TDU_MCONTROL_TYPE_VAL’ expects 4 bits on the Initial value, but Initial value’s CONST ‘2’h2′ generates 2 bits. : … note: In instance ‘max10’ 72 | SCR1_TDU_MCONTROL_TYPE_VAL = 2’d2; | ^~~~~~~~~~~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:78:25: Operator VAR ‘SCR1_TDU_MCONTROL_MASKMAX_VAL’ expects 6 bits on the Initial value, but Initial value’s CONST ‘1’h0′ generates 1 bits. : … note: In instance ‘max10’ 78 | SCR1_TDU_MCONTROL_MASKMAX_VAL = 1’b0; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:98:25: Operator VAR ‘SCR1_TDU_ICOUNT_TYPE_VAL’ expects 4 bits on the Initial value, but Initial value’s CONST ‘2’h3′ generates 2 bits. : … note: In instance ‘max10’ 98 | SCR1_TDU_ICOUNT_TYPE_VAL = 2’d3; | ^~~~~~~~~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/includes/scr1_tdu.svh:101:25: Operator VAR ‘SCR1_TDU_ICOUNT_RESERVEDB_VAL’ expects 2 bits on the Initial value, but Initial value’s CONST ‘1’h0′ generates 1 bits. : … note: In instance ‘max10’ 101 | SCR1_TDU_ICOUNT_RESERVEDB_VAL = 1’b0; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_top.sv:21:1: … note: In file included from ‘scr1_pipe_top.sv‘%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:409:30: Operator COND expects 64 bits on the Conditional False, but Conditional False’s SIGNED generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_exu.i_ialu’ 409 | assign mul_res = mdu_cmd_mul ? mul_op1 mul_op2 : $signed(‘0); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:467:23: Operator COND expects 32 bits on the Conditional True, but Conditional True’s REPLICATE generates 2 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_exu.i_ialu’ 467 | ? {‘0, div_quo_bit} | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:506:40: Operator COND expects 33 bits on the Conditional True, but Conditional True’s SIGNED generates 2 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_exu.i_ialu’ 506 | : mdu_fsm_idle ? $signed({div_op1_is_neg, exu2ialu_main_op1_i[32-1]}) | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:596:58: Operator XOR expects 32 bits on the LHS, but LHS’s SEL generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_exu.i_ialu’ 596 | ialu2exu_main_res_o = 32′(~(main_sum_flags.s ^ main_sum_flags.o)); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:596:58: Operator XOR expects 32 bits on the RHS, but RHS’s SEL generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_exu.i_ialu’ 596 | ialu2exu_main_res_o = 32′(~(main_sum_flags.s ^ main_sum_flags.o)); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_ipic.sv:396:38: Operator COND expects 5 bits on the Conditional False, but Conditional False’s CONST ‘1’h0′ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ipic’ 396 | : ipic_eoi_req ? irq_eoi_req_vd ? {1’b0, irq_eoi_req_idx} | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_exu.sv:939:26: Operator COND expects 32 bits on the Conditional False, but Conditional False’s REPLICATE generates 6 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_exu’ 939 | ? mprf2exu_rs1_data_i | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_hdu.sv:550:43: Operator EQ expects 32 bits on the LHS, but LHS’s VARREF ‘pbuf_addr_ff’ generates 3 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_hdu’ 550 | assign pbuf_addr_end = (pbuf_addr_ff == (SCR1_HDU_PBUF_ADDR_SPAN-1)); | ^~%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_hdu.sv:711:24: Operator ASSIGNDLY expects 3 bits on the Assign RHS, but Assign RHS’s CONST ‘1’h0′ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_hdu’ 711 | csr_dcsr_cause <= 1’b0; | ^~%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:450:79: Operator SUB expects 32 bits on the LHS, but LHS’s VARREF ‘q_wptr’ generates 3 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 450 | assign q_free_h_next = SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF — (q_wptr — q_rptr_next)); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:450:79: Operator SUB expects 32 bits on the RHS, but RHS’s VARREF ‘q_rptr_next’ generates 3 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 450 | assign q_free_h_next = SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF — (q_wptr — q_rptr_next)); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:531:89: Operator ADD expects 4 bits on the RHS, but RHS’s VARREF ‘imem_handshake_done’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 531 | : {imem_addr_ff[32-1:6], imem_addr_ff[5:2] + imem_handshake_done}; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:529:89: Operator ADD expects 30 bits on the RHS, but RHS’s VARREF ‘imem_handshake_done’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 529 | assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[32-1:2] + imem_handshake_done | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:530:97: Operator ADD expects 30 bits on the RHS, but RHS’s VARREF ‘imem_handshake_done’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 530 | : &imem_addr_ff[5:2] ? imem_addr_ff + imem_handshake_done | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:553:74: Operator SUB expects 3 bits on the LHS, but LHS’s VARREF ‘imem_handshake_done’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 553 | assign imem_pnd_txns_cnt_next = imem_pnd_txns_cnt + (imem_handshake_done — imem_resp_received); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:553:74: Operator SUB expects 3 bits on the RHS, but RHS’s VARREF ‘imem_resp_received’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 553 | assign imem_pnd_txns_cnt_next = imem_pnd_txns_cnt + (imem_handshake_done — imem_resp_received); | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:581:87: Operator SUB expects 3 bits on the RHS, but RHS’s VARREF ‘imem_handshake_done’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 581 | assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i ? imem_pnd_txns_cnt_next — imem_handshake_done | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_tdu.sv:173:33: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS’s REPLICATE generates 4 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_tdu’ 173 | tdu2csr_rdata_o = {‘0, csr_tselect_ff}; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_tdu.sv:226:40: Bit extraction of var[31:0] requires 5 bit index, not 4 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_tdu’ 226 | tdu2csr_rdata_o[SCR1_TDU_MCONTROL_TYPE_VAL] = 1’b1; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_tdu.sv:231:36: Bit extraction of var[31:0] requires 5 bit index, not 4 bits. : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_tdu’ 231 | tdu2csr_rdata_o[SCR1_TDU_ICOUNT_TYPE_VAL] = 1’b1; | ^%Warning-WIDTHEXPAND: ../../common/generic_fifos/rtl/verilog/generic_dpram.v:334:16: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS’s VARREF ‘start’ generates 4 bits. : … note: In instance ‘max10.u_sserial.u_serial_fifo.u0’ 334 | for (rnum=start;rnum<=finish;rnum=rnum+1) | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:465:64: Operator ASSIGN expects 9 bits on the Assign RHS, but Assign RHS’s VARREF ‘DMSTATUS_RESERVEDC’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 465 | SCR1_DBG_DMSTATUS_RESERVEDC_LO] = DMSTATUS_RESERVEDC; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:468:64: Operator ASSIGN expects 2 bits on the Assign RHS, but Assign RHS’s VARREF ‘DMSTATUS_RESERVEDB’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 468 | SCR1_DBG_DMSTATUS_RESERVEDB_LO] = DMSTATUS_RESERVEDB; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:486:64: Operator ASSIGN expects 4 bits on the Assign RHS, but Assign RHS’s VARREF ‘DMSTATUS_VERSION’ generates 2 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 486 | SCR1_DBG_DMSTATUS_VERSION_LO] = DMSTATUS_VERSION; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:497:64: Operator ASSIGN expects 10 bits on the Assign RHS, but Assign RHS’s VARREF ‘DMCONTROL_HARTSELLO’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 497 | SCR1_DBG_DMCONTROL_HARTSELLO_LO] = DMCONTROL_HARTSELLO; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:499:64: Operator ASSIGN expects 10 bits on the Assign RHS, but Assign RHS’s VARREF ‘DMCONTROL_HARTSELHI’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 499 | SCR1_DBG_DMCONTROL_HARTSELHI_LO] = DMCONTROL_HARTSELHI; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:501:64: Operator ASSIGN expects 4 bits on the Assign RHS, but Assign RHS’s VARREF ‘DMCONTROL_RESERVEDA’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 501 | SCR1_DBG_DMCONTROL_RESERVEDA_LO] = DMCONTROL_RESERVEDA; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:508:64: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS’s VARREF ‘ABSTRACTCS_RESERVEDD’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 508 | SCR1_DBG_ABSTRACTCS_RESERVEDD_LO] = ABSTRACTCS_RESERVEDD; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:512:64: Operator ASSIGN expects 11 bits on the Assign RHS, but Assign RHS’s VARREF ‘ABSTRACTCS_RESERVEDC’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 512 | SCR1_DBG_ABSTRACTCS_RESERVEDC_LO] = ABSTRACTCS_RESERVEDC; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:518:64: Operator ASSIGN expects 4 bits on the Assign RHS, but Assign RHS’s VARREF ‘ABSTRACTCS_RESERVEDA’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 518 | SCR1_DBG_ABSTRACTCS_RESERVEDA_LO] = ABSTRACTCS_RESERVEDA; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:525:64: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS’s VARREF ‘HARTINFO_RESERVEDB’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 525 | SCR1_DBG_HARTINFO_RESERVEDB_LO] = HARTINFO_RESERVEDB; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:529:64: Operator ASSIGN expects 3 bits on the Assign RHS, but Assign RHS’s VARREF ‘HARTINFO_RESERVEDA’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 529 | SCR1_DBG_HARTINFO_RESERVEDA_LO] = HARTINFO_RESERVEDA; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:756:49: Operator EQ expects 8 bits on the RHS, but RHS’s VARREF ‘ABS_CMD_HARTREG’ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 756 | assign abs_cmd_hartreg_vd = (abs_cmd_type == ABS_CMD_HARTREG) & abs_cmd_regvalid; | ^~%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:757:49: Operator EQ expects 8 bits on the RHS, but RHS’s VARREF ‘ABS_CMD_HARTMEM’ generates 2 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 757 | assign abs_cmd_hartmem_vd = (abs_cmd_type == ABS_CMD_HARTMEM) & abs_cmd_memvalid; | ^~%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:1135:40: Operator AND expects 3 bits on the LHS, but LHS’s CASTWRAP generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dm’ 1135 | & (~dmi2dm_wdata_i[SCR1_DBG_ABSTRACTCS_CMDERR_HI: | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:101:47: Operator EQ expects 2 bits on the RHS, but RHS’s CONST ‘1’h1′ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 101 | assign tapc_dtmcs_sel = (tapcsync2dmi_ch_id_i == 1’d1); | ^~%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:108:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 108 | tap_dr_rdata[DTMCS_RESERVEDB_HI:DTMCS_RESERVEDB_LO] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:109:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 109 | tap_dr_rdata[DTMCS_DMIHARDRESET] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:110:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 110 | tap_dr_rdata[DTMCS_DMIRESET] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:111:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 111 | tap_dr_rdata[DTMCS_RESERVEDA] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:112:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 112 | tap_dr_rdata[DTMCS_IDLE_HI:DTMCS_IDLE_LO] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:113:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 113 | tap_dr_rdata[DTMCS_DMISTAT_HI:DTMCS_DMISTAT_LO] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:114:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 114 | tap_dr_rdata[DTMCS_ABITS_HI :DTMCS_ABITS_LO] = SCR1_DBG_DMI_ADDR_WIDTH; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:115:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 115 | tap_dr_rdata[DTMCS_VERSION_LO] = 1’b1; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:119:21: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 119 | tap_dr_rdata[DMI_OP_HI :DMI_OP_LO] = ‘b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:156:28: Operator ASSIGN expects 7 bits on the Assign RHS, but Assign RHS’s CONST ‘1’h0′ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 156 | dmi2dm_addr_o = 1’b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:157:28: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS’s CONST ‘1’h0′ generates 1 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 157 | dmi2dm_wdata_o = 1’b0; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:160:35: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 160 | dmi2dm_req_o = tap_dr_ff[DMI_OP_HI :DMI_OP_LO] != 2’b00; | ^%Warning-WIDTHEXPAND: ../../../riscv-cores/scr1/src/core/scr1_dmi.sv:161:35: Bit extraction of var[40:0] requires 6 bit index, not 5 bits. : … note: In instance ‘max10.i_top.i_core_top.i_dmi’ 161 | dmi2dm_wr_o = tap_dr_ff[DMI_OP_HI :DMI_OP_LO] == 2’b10; | ^%Warning-WIDTHTRUNC: ../../common/sserial.v:57:4: Logical operator IF expects 1 bit on the If, but If’s VARREF ‘serial_cnt’ generates 4 bits. : … note: In instance ‘max10.u_sserial’ 57 | if(serial_cnt) | ^~ … For warning description see https://verilator.org/warn/WIDTHTRUNC?v=5.037 … Use «/* verilator lint_off WIDTHTRUNC /» and lint_on around source to disable this message.%Warning-UNSIGNED: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_idu.sv:928:30: Comparison is constant due to unsigned arithmetic : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_idu’ 928 | ((idu2exu_cmd_o.ialu_cmd >= SCR1_IALU_CMD_NONE) & | ^~ … For warning description see https://verilator.org/warn/UNSIGNED?v=5.037 … Use «/ verilator lint_off UNSIGNED /» and lint_on around source to disable this message.%Warning-UNSIGNED: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:788:28: Comparison is constant due to unsigned arithmetic : … note: In instance ‘max10.i_top.i_core_top.i_pipe_top.i_pipe_ifu’ 788 | (imem_resp_discard_cnt >= 0) & (imem_resp_discard_cnt <= imem_pnd_txns_cnt) | ^~%Warning-CASEINCOMPLETE: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ifu.sv:426:9: Case values incompletely covered (example pattern 0x0) 426 | case (q_wr_size) | ^~~~ … For warning description see https://verilator.org/warn/CASEINCOMPLETE?v=5.037 … Use «/ verilator lint_off CASEINCOMPLETE /» and lint_on around source to disable this message.%Warning-CASEINCOMPLETE: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:352:9: Case values incompletely covered (example pattern 0x3) 352 | case (mdu_fsm_ff) | ^~~~%Warning-CASEINCOMPLETE: ../../../riscv-cores/scr1/src/core/pipeline/scr1_pipe_ialu.sv:634:13: Case values incompletely covered (example pattern 0x3) 634 | case (mdu_fsm_ff) | ^~~~%Warning-CASEINCOMPLETE: ../../../riscv-cores/scr1/src/core/scr1_dm.sv:821:5: Case values incompletely covered (example pattern 0xd) 821 | case (abs_fsm_ff) | ^~~~%Warning-MULTIDRIVEN: ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:60:17: Signal has multiple driving blocks with different clocking: ‘max10.i_top.i_core_top.i_tapc_synchronizer.dmi_ch_capture_sync’ ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:126:9: … Location of first driving block 126 | dmi_ch_capture_sync[2:1] <= {dmi_ch_capture_sync[1], dmi_ch_capture_sync[0]}; | ^~~~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:113:9: … Location of other driving block 113 | dmi_ch_capture_sync[0] <= ‘0; | ^~~~~~~~~~~~~~~~~~~ … For warning description see https://verilator.org/warn/MULTIDRIVEN?v=5.037 … Use «/ verilator lint_off MULTIDRIVEN /» and lint_on around source to disable this message.%Warning-MULTIDRIVEN: ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:61:17: Signal has multiple driving blocks with different clocking: ‘max10.i_top.i_core_top.i_tapc_synchronizer.dmi_ch_shift_sync’ ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:127:9: … Location of first driving block 127 | dmi_ch_shift_sync[2:1] <= {dmi_ch_shift_sync[1], dmi_ch_shift_sync[0]}; | ^~~~~~~~~~~~~~~~~ ../../../riscv-cores/scr1/src/core/scr1_tapc_synchronizer.sv:114:9: … Location of other driving block 114 | dmi_ch_shift_sync[0] <= ‘0; | ^~~~~~~~~~~~~~~~~%Warning-MULTIDRIVEN: ../../../riscv-cores/scr1/src/top/scr1_timer.sv:65:53: Signal has multiple driving blocks with different clocking: ‘max10.i_top.i_timer.rtc_sync’ ../../../riscv-cores/scr1/src/top/scr1_timer.sv:204:13: … Location of first driving block 204 | rtc_sync[3:1] <= rtc_sync[2:0]; | ^~~~~~~~ ../../../riscv-cores/scr1/src/top/scr1_timer.sv:194:13: … Location of other driving block 194 | rtc_sync[0] <= ~rtc_sync[0]; | ^~~~~~~~%Warning-UNOPTFLAT: ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:153:24: Signal unoptimizable: Circular combinational logic: ‘max10.u_sserial.u_serial_fifo.rp_bin_x’ 153 | wire [aw:0] wp_bin_x, rp_bin_x; | ^~~~~~~~ … For warning description see https://verilator.org/warn/UNOPTFLAT?v=5.037 … Use «/ verilator lint_off UNOPTFLAT /» and lint_on around source to disable this message. ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:153:24: Example path: max10.u_sserial.u_serial_fifo.rp_bin_x ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:278:17: Example path: ASSIGNW ../../common/generic_fifos/rtl/verilog/generic_fifo_dc_gray.v:153:24: Example path: max10.u_sserial.u_serial_fifo.rp_bin_x- V e r i l a t i o n R e p o r t: Verilator 5.037 devel rev v5.036-174-g17c2512d0- Verilator: Built from 16.261 MB sources in 41 modules, into 1.835 MB in 12 C++ files needing 0.001 MB- Verilator: Walltime 0.212 s (elab=0.022, cvt=0.122, bld=0.000); cpu 0.206 s on 1 threads; alloced 34.949 MBg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Os -c -o tb.o /home/nick/fpga/riscv-compare/FPGA/m3-scr1/sim/tb.cppg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -c -o verilated.o /usr/local/share/verilator/include/verilated.cppg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -c -o verilated_threads.o /usr/local/share/verilator/include/verilated_threads.cppg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -x c++-header Vmax10__pch.h -o Vmax10__pch.h.fast.gchg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.fast -c -o Vmax10.o Vmax10.cppg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.fast -c -o Vmax10___024root__DepSet_h093b22e1__0.o Vmax10___024root__DepSet_h093b22e1__0.cppg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.fast -c -o Vmax10___024root__DepSet_hedb980a7__0.o Vmax10___024root__DepSet_hedb980a7__0.cppg++ -Os -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.fast -c -o Vmax10___024root__DepSet_hedb980a7__1.o Vmax10___024root__DepSet_hedb980a7__1.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -x c++-header Vmax10__pch.h -o Vmax10__pch.h.slow.gchg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10__ConstPool_0.o Vmax10__ConstPool_0.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10___024root__Slow.o Vmax10___024root__Slow.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10___024root__DepSet_h093b22e1__0__Slow.o Vmax10___024root__DepSet_h093b22e1__0__Slow.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10___024root__DepSet_hedb980a7__0__Slow.o Vmax10___024root__DepSet_hedb980a7__0__Slow.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10___024root__DepSet_hedb980a7__1__Slow.o Vmax10___024root__DepSet_hedb980a7__1__Slow.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10___024unit__Slow.o Vmax10___024unit__Slow.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10___024unit__DepSet_hc138aaae__0__Slow.o Vmax10___024unit__DepSet_hc138aaae__0__Slow.cppg++ -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TIMING=0 -DVM_TRACE=0 -DVM_TRACE_FST=0 -DVM_TRACE_VCD=0 -DVM_TRACE_SAIF=0 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-shadow -Wno-sign-compare -Wno-subobject-linkage -Wno-tautological-compare -Wno-uninitialized -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -include Vmax10__pch.h.slow -c -o Vmax10__Syms.o Vmax10__Syms.cppecho «» > Vmax10__ALL.verilator_deplist.tmpg++ tb.o verilated.o verilated_threads.o Vmax10__ALL.a -pthread -lpthread -latomic -o Vmax10rm Vmax10__ALL.verilator_deplist.tmp***************************************************** Start Simulator ******************************************************Testbench started!TCM memory content from start address 0: 00000093 00000113 00000193 00000213 00000293 00000313 00000393 00000413STARTDhrystone Benchmark, Version 2.1 (Language: C)Program compiled without ‘register’ attributeExecution starts, 500 runs through DhrystoneExecution endsFinal values of the variables used in the benchmark:Int_Glob: 5 should be: 5Bool_Glob: 1 should be: 1Ch_1_Glob: A should be: ACh_2_Glob: B should be: BArr_1_Glob[8]: 7 should be: 7Arr_2_Glob[8][7]: 510 should be: Number_Of_Runs + 10Ptr_Glob-> Ptr_Comp: 12540 should be: (implementation-dependent) Discr: 0 should be: 0 Enum_Comp: 2 should be: 2 Int_Comp: 17 should be: 17 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRINGNext_Ptr_Glob-> Ptr_Comp: 12540 should be: (implementation-dependent), same as above Discr: 0 should be: 0 Enum_Comp: 1 should be: 1 Int_Comp: 18 should be: 18 Str_Comp: DHRYSTONE PROGRAM, SOME STRING should be: DHRYSTONE PROGRAM, SOME STRINGInt_1_Loc: 5 should be: 5Int_2_Loc: 13 should be: 13Int_3_Loc: 7 should be: 7Enum_Loc: 1 should be: 1Str_1_Loc: DHRYSTONE PROGRAM, 1’ST STRING should be: DHRYSTONE PROGRAM, 1’ST STRINGStr_2_Loc: DHRYSTONE PROGRAM, 2’ND STRING should be: DHRYSTONE PROGRAM, 2’ND STRINGBeginTime 19201 EndTime 245752 UserTime 226551Number_Of_Runs= 500, HZ= 1000000Time: begin= 19201, end= 245752, diff= 226551Microseconds for one run through Dhrystone: 453Dhrystones per Second: 2207Cycles_Per_Instruction: 1.742Seg4x7 register Written 00002207DONE- ../../m3-scr1/max10.v:182: Verilog $finishTestbench finished!
Обратите внимание, что в конце симуляции лог выдаёт число Dhrystones per Second и у разных ядер это число разное! Для SOC с процессором SCR1 в конфигурации IM это число 2207.
Компиляция проектов FPGA scr1 и picorv32 SOC.
Проекты SOC для picorv32 и для scr1 находятся в папках riscv-compare/FPGA/m3-picorv32 и riscv-compare/FPGA/m3-scr1 соответственно. Нужно запустить САПР Quartus Prime, перейти в нужную папку и открыть проект.
После того, как откроете проект нужно выбрать ревизию проекта через меню квартуса Project -> Revisions. Например, для SOC Scr1 есть четыре мною определенных ревизий для двух плат Марсоход3 и Марсоход3бис — они отличаются установленным чипом MAX10 и количеством имеющихся в нем логических элементов 50 тысяч или 8 тысяч. Для каждой из плат определено так же какая конфигурация процессора будет использована минимальная EC или максимальная IM.
Всего 4 ревизии проекта описаны в файле max10.qpf (Quartus Project File):
QUARTUS_VERSION = "23.1"DATE = "19:24:25 April 23, 2026"# RevisionsPROJECT_REVISION = "max10_8K_ec"PROJECT_REVISION = "max10_50K_im"PROJECT_REVISION = "max10_50K_ec"PROJECT_REVISION = "max10_8K_im"
Выбираете интересующую вас ревизию, компилируете для вашей платы и загружаете в ПЛИС.
На семи-сегментном индикаторе платы вы увидите значение Dhrystone теста:
К плате можно подключиться через последовательный порт на скорости 12Мбит/сек и тогда можно увидеть вывод всей программы Dhrystone в консоли Putty:
Как вы можете заметить, результат симуляции с Verilator и запуск в реальной плате Марсоход3 отображают в консоли и на семи-сегментном индикаторе одно и то же число измеренной производительности 2207!
В среде квартус есть полезные отчеты компилятора из которых мы узнаем максимальную частоту Fmax, которую возможно использовать на ядре и которую обещает Quartus, а так же количество использованных ресурсов FPGA: регистров, памяти, умножителей и так далее. Например, вот Resource Usage by Entity:
Отсюда и из других отчетов я буду брать значения для итоговой таблицы измерений.
Итоговая таблица измерений.

Вот диаграмма Fmax для разных проектов, как её рапортует САПР Quartus:
Из этой таблицы и диаграммы видно, что видимо ядро scr1 более сложное, оно содержит больше логики и требует больше регистров. Соответственно и максимальная возможная тактовая частота для моей FPGA получается ниже. При всём при этом, это ядро явно быстрее, так как выполняет инструкции за меньшее число тактов процессора.
Ниже я приведу построенные по этой таблице диаграммы производительности.
Диаграмма производительности ядер scr1 и picorv32 в единицах измерения Dhrystone. Интересно, что процессор scr1 в минимальной конфигурации EC почти не уступает максимальной конфигурации IM, но так, как Fmax проекта у EC оказалась выше, то в целом его можно быстрее разогнать и даже обойти в производительности конфигурацию IM.
Ну и видно, что процессор scr1 явно выигрывает по производительности у picorv32 даже в пересчёте на Fmax.
Мои FPGA проекты подают на ядро процессора 20МГц. Значит пересчет на Fmax будет Dhry/20*Fmax. Вот так я это считаю.
Ну и по ресурсам. Конечно, picorv32 оказывается более компактным:
Ядру picorv32 нужно меньше логики и регистров для нормального функционирования.
В целом результат ожидаемый. Более сложная архитектура scr1 позволяет улучшить производительность, но она требует больших ресурсов в FPGA.
Ну и в конце я хотел бы добавить, что мне одинаково симпатичны оба ядра и scr1 и picorv32. Они несомненно могут быть использованы во встраиваемых приложениях. Ну а какое ядро использовать в проектах уже решать вам.
Ещё хотел бы добавить, что одна из важных и интересных особенностей процессора scr1 это настоящая поддержка JTAG отладки. Через JTAG можно вести отладку программ работающих прямо в процессоре с помощью отладчика GDB. И для этого на самом деле даже и плата не нужна. Я уже написал, как вести отладку ядра scr1 работающего под симулятором Verilator через виртуальный JTAG.
Однако учтите, что сейчас в моем проекте я подключил к линиям JTAG просто константы ноль, то есть они не работают и значит компилятор выбросил из анализа всю связанную логику. С работающим JTAG процессор scr1 будет занимать гораздо больше места в ПЛИС.
Что касается ядра микроконтроллера picorv32, то его довольно просто запустить даже на платах с ограниченными ресурсами. Например, я запускал это ядро на плате Марсоход3WG2 с микросхемой ПЛИС от Gowin. Исходники этого проекта так же есть на Github.
ссылка на оригинал статьи https://habr.com/ru/articles/1027538/