alex1985 0 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Доброго всем времени суток! Прошу меня сильно не пинать, Verilog начал изучать совсем недавно. Модуль не хочет работать ни в симуляторе, ни в железе( Код программы, RTL и скрин симуляции прилагаются, могу скинуть исходный код. Проект собирается в Quartus II 9.1, ПЛИС cyclone III. Код: module MEM_CONTROLLER ( input clk, cs, input [15:0] data_in, output [15:0] data_out, output reg [3:0] addr, output wr ); reg [15:0] data_out_reg; reg [2:0] state; reg b_write; //Если 1 - то записываем данные reg wr_reg; parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4, S5 = 5, S6 = 6; always @ (posedge clk) begin case (state) //--------------------------- // Ждем спад 1 cs //--------------------------- S0: if (cs==0) state <= S1; else state <= S0; //--------------------------- // Фронт 1 cs, заносим адрес в регистр addr // Если старший бит = 1 - то записываем данные в RAM, // иначе - читаем //--------------------------- S1: if (cs) begin case (data_in[2:0]) 3'b001 : addr <= 4'b0001; 3'b010 : addr <= 4'b0010; 3'b011 : addr <= 4'b0100; 3'b100 : addr <= 4'b1000; default : addr <= 4'b0000; endcase b_write <= data_in[15]? 1'b1:1'b0; state <= S2; end else state <= S1; //--------------------------- // Ждем спад 2 cs //--------------------------- S2: if (cs==0) state <= S3; else state <= S2; //--------------------------- // Ждем фронт 2 cs //--------------------------- S3: if (cs) if (b_write) begin data_out_reg[15:0] <= data_in[15:0]; state <= S4; end else state <= S0; //Читаем данные (выводим их на data_out) else state <= S3; //--------------------------- // Ждем установки addr // Устанавливаем wr = 1 //--------------------------- S4: begin wr_reg <= 1; state <= S5; end //--------------------------- // Сбрасываем wr //--------------------------- S5: begin wr_reg <= 0; state <= S0; end //--------------------------- endcase end assign data_out[15:0] = data_out_reg[15:0]; assign wr = wr_reg; endmodule RTL: Waveform: В симулиции по логике там где стоит маркер должен происходить переход в состояние S2, но ничего не происходит( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Прошу меня сильно не пинать, Verilog начал изучать совсем недавно. Модуль не хочет работать ни в симуляторе, ни в железе 1. Я бы посоветовал проводить симуляцию не тем симулятором, который поставляется вместе с Quartus, а в таких симуляторах, как например, Modelsim или AtiveHDL. У всех есть бесплатные версии с ограничениями. 2. Начните описывать автоматы 3 классическими always блоками : Первый блок синхронный - переключение состояний автомата. Второй блок комбинационный - вычисление следующего состояния автомата. Третий блок комбинационный - выходня логика автомата. И лишь тогда, когда Вы научитесь правильно описывать автоматы таким стилем, только тогда переходите к другим стилям описания автомата. Сейчас Вы выбрали самый сложный стиль описания, где допустить ошибку очень и очень просто. А найти её, да ещё при использовании альтеровского симулятора, очень сложно. 3. Ну и присвойте нормальные имена состояниям автомата вместо: parameter S1 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4, S5 = 5, S6 = 6; Правильно присвоенные имена - очень помогают ориентироваться по коду ,особенно людям с ним незнакомым, а также избежать ошибок. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
1891ВМ12Я 0 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Модуль не хочет работать ни в симуляторе, ни в железе Не вижу ничего криминального, сам так пишу. Но вот какой смысл писать эти S0 S1,2...? Просто числа, либо идентификаторы. А тут можно просто числами ограничиться было. Первое что заметил, в Verilog все имена зависят от высоты букв, поэтому разумеется что CS и cs это разные переменные для Verilog и в S2 мы так никогда и не попадем, хотя я не вижу код тестбенча, чтобы утверждать точно. Далее, симулятор показывает белиберду в state.S0..N, почему нельзя просто вывести state ввиде числа и там было бы всё ясно и однозначно. В общем, нужен опыт и всё станет хорошо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 10 мая, 2018 Опубликовано 10 мая, 2018 (изменено) · Жалоба 2. Начните описывать автоматы 3 классическими always блоками : Первый блок синхронный - переключение состояний автомата. Второй блок комбинационный - вычисление следующего состояния автомата. Третий блок комбинационный - выходня логика автомата. И лишь тогда, когда Вы научитесь правильно описывать автоматы таким стилем, только тогда переходите к другим стилям описания автомата. Сейчас Вы выбрали самый сложный стиль описания, где допустить ошибку очень и очень просто. А найти её, да ещё при использовании альтеровского симулятора, очень сложно. А можно чуть подробнее? Для реализации state-машины я использовал стандартный шаблон автомата Мура: module four_state_moore_state_machine ( input clk, in, reset, output reg [1:0] out ); // Declare state register reg [1:0]state; // Declare states parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3; // Output depends only on the state always @ (state) begin case (state) S0: out = 2'b01; S1: out = 2'b10; S2: out = 2'b11; S3: out = 2'b00; default: out = 2'b00; endcase end // Determine the next state always @ (posedge clk or posedge reset) begin if (reset) state <= S0; else case (state) S0: state <= S1; S1: if (in) state <= S2; else state <= S1; S2: if (in) state <= S3; else state <= S1; S3: if (in) state <= S2; else state <= S3; endcase end endmodule Но здесь всего 2 блока: синхронный (Determine the next state) и комбинационный - вычисление следующего состояния автомата (Output depends only on the state). О каком третьем блоке Вы говорите? Насчет имен состояний полностью согласен - напишу что-нибудь более вразумительное. Изменено 10 мая, 2018 пользователем Sprite Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Сейчас Вы выбрали самый сложный стиль описания, где допустить ошибку очень и очень просто.Я придерживаюсь прямо противоположного взгляда. Ничего простого и удобного в размазывании КА по нескольким процессам не вижу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Я придерживаюсь прямо противоположного взгляда. Ничего простого и удобного в размазывании КА по нескольким процессам не вижу. У Вас опыта гораздо больше . Согласен, что несколько неудобно, т.к описание такого КА получается достаточно громоздким. Но при разделении автомата на 3 процесса - меньше шансов наделать ошибок, особенно это важно для начинающих. Считаю, что сначала надо научиться делать "классически" и "неудобно" - и когда будет полное понимание того, что происходит при описании автомата и в какую схему в итоге это выливается(да и вообще важно понимать что схемотехнически представляет собой цифровой автомат), тогда можно писать удобным для себя стилем, опять-же с полным пониманием зачем и почему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба По совету Flip-fl0p переделал state-машину на 2 always-блока: module MEM_CONTROLLER ( input clk, cs, input [15:0] data_in, output reg[15:0] data_out, output reg[3:0] addr, output reg wr ); reg [15:0] data_out_reg; reg [3:0] addr_reg; reg b_write; //Если 1 - то записываем данные reg wr_reg; initial begin data_out_reg = 15'b0; addr_reg = 4'b0; end reg [2:0] state; parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4; // Output depends only on the state always @ (state, data_out_reg, addr_reg, data_in) begin case (state) S0,S1,S2,S3: begin data_out[15:0] = data_out_reg[15:0]; addr[3:0] = addr_reg[3:0]; wr = 1'b0; end S4: begin data_out[15:0] = data_in[15:0]; addr[3:0] = addr_reg[3:0]; wr = 1'b1; end default: begin data_out[15:0] = 15'b0; addr[3:0] = 4'b0; wr = 1'b0; end endcase end always @ (posedge clk) begin case (state) //--------------------------- // Ждем спад 1 cs //--------------------------- S0: if (cs==0) state <= S1; else state <= S0; //--------------------------- // Ждем фронт 1 cs, заносим адрес в регистр addr // Если старший бит в адресе = 1 - то записываем данные, // иначе - читаем //--------------------------- S1: if (cs) begin case (data_in[2:0]) 3'b001 : addr_reg <= 4'b0001; 3'b010 : addr_reg <= 4'b0010; 3'b011 : addr_reg <= 4'b0100; 3'b100 : addr_reg <= 4'b1000; default : addr_reg <= 4'b0000; endcase b_write <= data_in[15]? 1'b1:1'b0; state <= S2; end else state <= S1; //--------------------------- // Ждем спада 2 cs //--------------------------- S2: if (cs==0) state <= S3; else state <= S2; //--------------------------- // Ждем фронт 2 cs //--------------------------- S3: if (cs) if (b_write) state <= S4; else state <= S0; //Читаем данные (выводим их на data_out) else state <= S3; //--------------------------- // Устанавливаем wr = 1 //--------------------------- S4: state <= S0; //--------------------------- endcase end endmodule В результате получилась более компактная и понятная RTL-схема: И симуляция частично поправилась: Только теперь значение data_out меняется только на момент состояния S4, при этом не сохраняя измененное значение ( Как это можно поправить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 6 10 мая, 2018 Опубликовано 10 мая, 2018 (изменено) · Жалоба Только теперь значение data_out меняется только на момент состояния S4, при этом не сохраняя измененное значение ( Как это можно поправить? Начать действовать последовательно и осмысленно. Во-первых, если вы отлаживаете FSM, то нужно и смотреть FSM (регистр state), и входные сигналы, которые влияют на переход из одного состояния в другое. Соответвствие выходов состоянию отладите позже. Но если вы считаете, что автомат проходит по состояниям верно, то отлажвайте выходы. В вашем коде, в состояниях, кроме S4 data_out равно значению регистра, который инициализируется, но присваиваний которому не производится, т.е. он неизменный на протяжении работы системы, потому и data_out не изменяется. А в состоянии S4 сигналу data_out присваивается другое значение. То есть, всё работает так, как написано, и если вы хотите другого поведения, то его надо определить и описать в коде. Изменено 10 мая, 2018 пользователем one_eight_seven Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Только теперь значение data_out меняется только на момент состояния S4, при этом не сохраняя измененное значение ( Как это можно поправить? Потому-что data_out у вас мультиплексор, который в состоянии S4: выдает то, что на входе (data_in) : data_out[15:0] = data_in[15:0]; addr[3:0] = addr_reg[3:0]; wr = 1'b1; а в остальных состояниях выдает нули. default: begin data_out[15:0] = 15'b0; addr[3:0] = 4'b0; wr = 1'b0; end Делать надо немного по-другому. В состоянии S4 выдается сигнал разрешения записи в регистр: S4: begin write_ena = '1'; end И где-то описать эти регистры(Verilog только читаю, а не пишу на нем. Мог допустить ошибки. Передал суть): always @ (posedge clk) begin if (write_ena) begin data_out[15:0] = 15'b0; addr[3:0] = 4'b0; wr = 1'b0; end end Вот тут посмотрите : http://www.asic-world.com/tidbits/verilog_fsm.html P.S. А почему такая старая версия Quartus ? Последняя версия, поддерживающая Cyclone III - Quartus 13.1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bogaev_roman 0 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба to Sprite Посмотрел я на времянку и мозг отказал минут на 5 - как машина может находиться одновременно в нескольких состояниях? Там вообще мусор должен быть на моделировании - начальное состояние не определено - либо сброс добавьте, либо начальное условие при инициализации. Или это картинка не моделирования, а сигнал тап? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Ошибся я немного. Переписал state-машину: // Output depends only on the state always @ (state, data_out, addr_reg, data_in) begin case (state) S0,S1,S2,S3: begin data_out[15:0] = [b]data_out[15:0];[/b] addr[3:0] = addr_reg[3:0]; wr = 1'b0; end S4: begin data_out[15:0] = data_in[15:0]; addr[3:0] = addr_reg[3:0]; wr = 1'b1; end default: begin data_out[15:0] = 15'b0; addr[3:0] = 4'b0; wr = 1'b0; end endcase end Вместо data_out_reg[15:0] нужно было делать присвоение data_out[15:0] < data_out[15:0]. Естественно все заработало) Только вылезла целая куча варнингов, типа: Warning (10240): Verilog HDL Always Construct warning at MEM_CONTROLLER.v(27): inferring latch(es) for variable "data_out", which holds its previous value in one or more paths through the always construct Как я понял квартус ругается на наличие latch, но именно так я и планировал. RTL-схема: и правильный waveform: Конечно, некрасиво с варнингами, буду думать как устранить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба Как я понял квартус ругается на наличие latch, но именно так я и планировал. А Вы читали, что я Вам писал ? Latch - в 99% случаев это ошибка. Вы пытаетесь в комбинационном блоке сохранить значения. Ну Qurtus и сделал Вам защелку, как Вы и просили его. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 10 мая, 2018 Опубликовано 10 мая, 2018 (изменено) · Жалоба Как я понял квартус ругается на наличие latch, но именно так я и планировал. А Вы читали, что я Вам писал ? Latch - в 99% случаев это ошибка. Вы пытаетесь в комбинационном блоке сохранить значения. Ну Qurtus и сделал Вам защелку, как Вы и просили его. Поправил) Вынес защелку в отдельный блок: module MEM_CONTROLLER ( input clk, cs, input [15:0] data_in, output [15:0] data_out, output [3:0] addr, output wr ); reg [15:0] data_out_reg; reg [3:0] addr_reg; reg b_write; //Если 1 - то записываем данные reg wr_reg; initial begin data_out_reg = 15'b0; addr_reg = 4'b0; end reg [2:0] state; parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4, S5 = 5; always @ (posedge clk) begin case (state) //--------------------------- // Ждем спад 1 cs //--------------------------- S0: if (cs==0) state <= S1; else state <= S0; //--------------------------- // Ждем фронт 1 cs, заносим адрес в регистр addr // Если старший бит в адресе = 1 - то записываем данные, // иначе - читаем //--------------------------- S1: if (cs) begin case (data_in[2:0]) 3'b001 : addr_reg <= 4'b0001; 3'b010 : addr_reg <= 4'b0010; 3'b011 : addr_reg <= 4'b0100; 3'b100 : addr_reg <= 4'b1000; default : addr_reg <= 4'b0000; endcase b_write <= data_in[15]? 1'b1:1'b0; state <= S2; end else state <= S1; //--------------------------- // Ждем спад 2 cs //--------------------------- S2: if (cs==0) state <= S3; else state <= S2; //--------------------------- // Ждем фронт 2 cs, устанавливаем wr_reg //--------------------------- S3: if (cs) if (b_write) state <= S4; else state <= S0; //Читаем данные (выводим их на data_out) else state <= S3; //--------------------------- // Устанавливаем wr_reg //--------------------------- S4: begin wr_reg <= 1'b1; state <= S5; end //--------------------------- // Сбрасываем wr_reg //--------------------------- S5: begin wr_reg <= 1'b0; state <= S0; end //--------------------------- endcase end //--------------------------- // Блок-защелка данных //--------------------------- always @ (posedge clk) begin if (state == S4) data_out_reg[15:0] = data_in[15:0]; end //--------------------------- assign data_out = data_out_reg; assign addr = addr_reg; assign wr = wr_reg; //--------------------------- endmodule RTL-схема: И нерабочий Waveform: В итоге пришел к самому первому варианту( Один большой плюс: варнинги исчезли)) Изменено 10 мая, 2018 пользователем Sprite Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MaratZuev 0 10 мая, 2018 Опубликовано 10 мая, 2018 · Жалоба //--------------------------- // Блок-защелка данных //--------------------------- always @ (posedge clk) begin if (state == S4) data_out_reg[15:0] = data_in[15:0]; end Это - не защёлка, а 15 параллельных триггеров: always @ (posedge clk) data_out_reg = state == S4 ? data_in : data_out_reg; А, вообще, давайте Ваш проект (тем более, что он небольшой) сюда (с тестбенчем, конечно): будет время - можно повозиться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 10 мая, 2018 Опубликовано 10 мая, 2018 (изменено) · Жалоба Это - не защёлка, а 15 параллельных триггеров: always @ (posedge clk) data_out_reg = state == S4 ? data_in : data_out_reg; А, вообще, давайте Ваш проект (тем более, что он небольшой) сюда (с тестбенчем, конечно): будет время - можно повозиться. Проект Во вложении. entity - test3.qpf Собирал в Quartus II 9.1, использовал для теста встроенный симулятор (файл test3.vwf) cyclone_III.rar Изменено 10 мая, 2018 пользователем Sprite Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться