МАРСОХОД

Open Source Hardware Project

ARM System-on-Chip

Amber ARM впервые работает на плате Марсоход2!

Вывод в консоль последовательного порта сообщения Hello, World!

Теперь уже работает – после нескольких исправлений в коде проекта Amber. Сейчас программа hello-world, написаннная на языке C и откомпилированная для ARM запускается в плате Марсоход2. Программа печатает сообщение функцией printf(..), которая отсылает его нам через последовательный порт на скорости 921600 бит/сек. А дело было так.

После симуляции проекта в Icarus Verilog я убедился, что сам проект Amber рабочий (вообще было бы странно, если бы он был нерабочим). Но проблема оставалась – в моем проекте Quartus II для ПЛИС Altera что-то видимо было сделано не верно.

Я использовал программу Altera Quartus II SignalTap, чтобы заглянуть внутрь ПЛИС. Теперь у меня была возможность сравнивать сигналы в симуляции с теми сигналами, которые я могу захватить логическим анализатором SignalTap.

Мой проект сделан таким образом, что вход с кнопочки (той, что ближе к разъему USB) платы Марсоход2 является сигналом сброса brd_n_rst  для проекта. Правда у самого процессора Amber сброса нет, но зато есть сигнал i_system_rdy, который я и связал со сбросом. Таким образом, процессор должен стартовать после того, как сигнал сброса будет снят. Это дает возможности для использования логического анализатора на самом старте процессора.

В SignalTap я задаю исследуемые сигналы, например внешние сигналы процессора к шине Wishbone bus. Я хочу посмотреть как процессор читает код программы из bootrom. Начальный момент захвата для логического анализатора (trigger) – это сигнал процесора i_system_rdy. Анализ внутренних сигналов в момент старта процессора производится следующим образом:

  • компилирую проект с включенным логическим анализатором и выбранными сигналами для анализа.
  • запускаю SignalTap.
  • на плате нажимаю кнопочку сброса для проекта Amber.
  • из SignalTap загружаю проект в ПЛИС – при этом проект не стартует, так как я держу кнопку сброса.
  • в SignalTap запускаю логический анализатор, который «подвисает» ожидая сигнала триггера на процессоре i_system_rdy.
  • отпускаю кнопочку сброса на плате – SignalTap тут же выдает мне картинку, как выглядят мои сигналы внутри ПЛИС Cyclone III.

Использование SignalTap для исследования внутренних сигналов процессора Amber

Используя этот метод я смог убедиться, что процессор на старте скорее мертв, чем жив. На шине Wishbone bus не происходит ничего, хотя адрес на bootrom выдается правильный – это ноль и с bootrom поступает первая команда процессора ARM 0xE3A00000 (это mov r0, #0x00000000). Другие сигналы шины o_wb_cyc, o_wb_stb, i_wb_ack не шевелятся.

Пришлось довольно долго повозиться рассматривая откуда эти сигналы берутся и от чего зависят. Каждая итерация занимает довольно много времени, поскольку, если я меняю список исследуемых сигналов в SignalTap мне требуется перекомпилировать проект.

В конце концов я добрался до одной очень странной странности – в модуле hw/vlog/amber23/a23_cache.v есть так называемая «машина состояний» (StateMachine) и похоже, что ее состояние при старте системы изначально не верное.

Использование SignalTap для исследования внутренних сигналов процессора Amber

Видите, что начальное состояние машины состояний в кэш контроллере c_state.CS_INIT = 1, но ведь должно быть не так! В коде Verilog a23_cache.v написано ведь совсем другое:

reg  [3:0] c_state = CS_IDLE;

Более того, если зайти в Quartus II в меню Tools => Netlist Viewers => State Machine Viewer то можно видеть, что компилятор Quartus II действительно неправильно определил поведение описанной на языке Verilog машины состояний.

Машина состояний кэш контроллера в проекте Amber

Quartus II считает, что у этой машины начальное состояние это CS_INIT, а должно быть CS_IDLE.

На самом деле мне трудно утверждать, что это именно баг компилятора Quartus II, возможно есть какие-то тонкости или неопределенности в стандарте языка Verilog. Я не являюсь досконольным знатоком спецификации Verilog. Все, что я утверждаю – написанное не соответствует скомпилированному и синтезированному в ПЛИС.

Очень странно, что даже явное указание начального значения для регистра c_state не меняет ситуацию, я написал вот так:

reg  [3:0] c_state = CS_IDLE;
initial
  c_state = CS_IDLE;


Но и это не помогло. Все из-за того, что, видимо, регистр c_state интерпретируется компилятором Quartus II каким-то особым образом из-за того, что описывает машину состояний. Очень странный баг (или фича?) в Quartus II.

В принципе в Quartus II есть множество настроек связанных с особенностями компиляции. Посмотреть их можно через меню Assignments => Settings и далее в диалоговом окне настройки Analysis & Synthesis Settings и далее кнопка More Settings.

Настройки компилятора Altera Quartus II

Здесь в списке есть Ignore Verilog initial constructs и у меня, как положенно, стоит здесь Off. Тоесть я хочу, чтобы initial constructs работали, чтобы в проекте при старте в регистрах были заданные в проекте значения.

В общем, помучавшись немного, я обнаружил здесь же в настройках другую полезную опцию – Extract Verilog State Machines – здесь стояло On. Это как раз та опция, которая заставляла компилятор Quartus интерпретировать регистр c_state не как обычный регистр, а как специфический регистр машины состояний. Как написано в подсказке Quartus эта опция позволяет:

Allows the Compiler to extract state machines from Verilog Design Files. The Compiler optimizes state machines using special techniques to reduce area and/or improve performance. If set to Off, the Compiler extracts and optimizes state machines in Verilog Design Files as regular logic.

Ага, как-же, дооптимизировали area и performance, что проект не правильно работает. В общем, выключил я эту опцию в настройках. Теперь Extract Verilog State Machines => Off.

Вы знаете, стало лучше, но не намного. Сигналы на Wishbone bus стали хоть как-то меняться, но все равно процессор не работает:

Использование SignalTap для исследования внутренних сигналов процессора Amber

После этого, я нашел еще одно место в проекте Amber неправильно интерпретируемое компилятором Quartus II – это в файле a23_decode.v

В этом файле выходные сигналы модуля объявляются и одновременно задается их начальное значение, вот так:


module a23_decode
(
input                       i_clk,
input       [31:0]          i_read_data,
...................
output reg  [31:0]          o_read_data = 1'd0,
output reg  [4:0]           o_read_data_alignment = 1'd0,  // 2 LSBs of read address used for calculating shift in LDRB ops

output reg  [31:0]          o_imm32 = 'd0,
output reg  [4:0]           o_imm_shift_amount = 'd0,
output reg                  o_shift_imm_zero = 'd0,
output reg  [3:0]           o_condition = 4'he,             // 4'he = al
output reg                  o_exclusive_exec = 'd0,         // exclusive access request ( swap instruction )
output reg                  o_data_access_exec = 'd0,       // high means the memory access is a read
// read or write, low for instruction
output reg  [1:0]           o_status_bits_mode = 2'b11,     // SVC
output reg                  o_status_bits_irq_mask = 1'd1,
output reg                  o_status_bits_firq_mask = 1'd1,
.................



Так вот получается, что все эти начальные значения для output reg проигнорированны компилятором. Я не смог найти опцию в настройках Quartus II, которая бы заставила использовать эти назначенные значения.

Пришлось ниже в тексте модуля задавать их явно с помощью конструкции initial.

 

Вот только после всех этих манипуляций с настройками проекта и изменений в коде a23_decode.v проект заработал и в консоли последовательного порта я увидел заветную фразу “Marsohod2: Hello, World!

Теперь и в SignalTap я вижу активный процесс чтения кода процессором из bootrom:

Использование SignalTap для исследования внутренних сигналов процессора Amber

Да и сообщение в консоли последовательного порта - это явное доказательство работоспособности проекта.

Вот теперь его можно и дальше развивать.

В общем, оказалось, что проект Amber использует какие-то конструкции языка Verilog, которые интерпретируются компилятором Quartus II несколько специфическим образом. Тем не менее, мы смогли это обойти исправив настройки проекта Altera Quartus II и несколько модифицировав исходный текст процессора Amber.

Все последние изменения в проекте есть на GitHub в нашем разделе https://github.com/marsohod4you/Amber-Marsohod2.

 

Комментарии  

0 #20 aivengo 08.10.2012 10:48
Цитирую afad:
Должно быть крутую систему строите, в которой 130 тыс. одинаковых блоков?

Да нет, скорее по незнанию. Хотел чтобы экран 272х485 очищался за один такт, но теперь мне это уже не кажется хорошей и реализуемой идеей)
0 #19 afad 08.10.2012 09:28
Цитирую aivengo:
Quartus за день не отсинтезировал код с циклом for до 130000. Подскажите пожалуйста, как решить проблему?
Должно быть крутую систему строите, в которой 130 тыс. одинаковых блоков?
0 #18 aivengo 07.10.2012 19:41
Quartus за день не отсинтезировал код с циклом for до 130000. Подскажите пожалуйста, как решить проблему?
0 #17 aivengo 07.10.2012 19:37
Здравствуйте!
Появилась необходимость использовать цикл for на 130 тысяч итераций:
for (i=0; i
0 #16 Антон 27.09.2012 10:53
а так пробовали?
// User-encoded state machine
(* syn_encoding = "user" *) reg [1:0] state;
0 #15 pixar 27.09.2012 09:49
Начальные установки действительно влияют , а FSM непричём . Bключал и просто one-hot и safe-mode. работает с любым. Quart11.0
0 #14 Nick1 26.09.2012 13:18
Статьи читаются как детективный роман. :lol: Хочется узнать что будет дальше?
0 #13 pixar 26.09.2012 06:39
Исходный проект под Спартан синтезирован , наверное, в Symplify. Может там с FSM что-то по другому строится ?
0 #12 tsdima 26.09.2012 06:03
Сообщение обрезалось...
Там есть такая строчка: c_state < = C_INIT
В данном случае, когда C_INIT=0 и CS_INIT=0, это роли не играет, но если менять значения localparam, то это надо считать ошибкой. Возможно не работало из-за этого. Или после исправлений машина состояний не изменилась?
0 #11 tsdima 26.09.2012 06:03
Сообщение обрезалось...
Там есть такая строчка: c_state
0 #10 tsdima 26.09.2012 06:00
Цитирую nckma:
Цитирую tsdima:
Начальное значение регистров как правило равно нулю, поэтому для машины состояний можно было сделать такое исправление:
localparam [3:0] CS_INIT = 4'd1,
CS_IDLE = 4'd0

я этот метод пробовал - не работает

Там есть такая строчка: c_state
0 #9 nckma 26.09.2012 04:30
Цитирую tsdima:
Начальное значение регистров как правило равно нулю, поэтому для машины состояний можно было сделать такое исправление:
localparam [3:0] CS_INIT = 4'd1,
CS_IDLE = 4'd0

я этот метод пробовал - не работает
0 #8 nckma 26.09.2012 04:29
Цитирую pixar:
always (posedge (clk) or negedge (rst))) begin
if ( reset ) begin
c_state

я понимаю, Вы хотите сказать, что нужно использовать сигнал reset для установки регистров в начальное значение. Проблема в том, что в процессоре Amber нет сигнала сброса. Конечно его можно самому дописать, но честно говоря хотелось бы обойтись минимальными изменениями, так как проект активно меняется автором. если он изменит процессор и мы захотим взять свежую версию, то придется сливать две ветки в одну. А это не всегда просто.
0 #7 pixar 26.09.2012 04:12
always (posedge (clk) or negedge (rst))) begin
if ( reset ) begin
c_state
0 #6 Angel007 25.09.2012 15:12
Браво!!!! Классную штуку вы тут делаете! Браво!!!
0 #5 nckma 25.09.2012 13:46
Цитирую afad:
Ух ты, здорово! Попробовал откомпилить проект. Получилось 91% (9340 из 10320) занятых логических блоков :sad:

если выключить SignalTap, то останется больше - он довольно много места занимает.
0 #4 afad 25.09.2012 12:49
Ух ты, здорово! Попробовал откомпилить проект. Получилось 91% (9340 из 10320) занятых логических блоков :sad:
0 #3 tsdima 25.09.2012 12:30
Начальное значение регистров как правило равно нулю, поэтому для машины состояний можно было сделать такое исправление:
localparam [3:0] CS_INIT = 4'd1,
CS_IDLE = 4'd0,

А вообще, должен быть сигнал сброса, который и устанавливает все начальные значения регистров, критических для запуска.
0 #2 Дмитрий 25.09.2012 11:47
Поздравляю с успехом :-) И ваш сайт во многом мне помогает.
0 #1 zrewa 25.09.2012 10:50
Отлично. :lol: Уникальный сайт. Теперь еще прикрутить контроллер памяти. Здесь, по-моему, тоже можно не изобретать велосипед и взять готовый. Самый лучший имхо HPDMC.

Добавить комментарий


Защитный код
Обновить


GitHub YouTube Twitter
Вы здесь: Начало Проекты Проект Марсоход2 Amber ARM SoC Amber ARM впервые работает на плате Марсоход2!