Jump to content
    

Реализация конечного автомата генератора последовательностей

Воспользовался ссылкой Muscat, создал файл Verilog Test Fixture, добавил кое-что из статьи, CLK и RST работают, DATA_O постоянно находится в состоянии ZZZZ, DATA_i в 0000, SEQ бежит начиная с F, A, D, 1, 6,...., 7, 8, F, т.е. по нашей последовательности. Верно?

Теперь еще нужно описать UP, LOAD и OE?

 

`timescale 1ns / 1ps

module fff;

// Inputs
reg clk;
reg rst;
reg load;
reg up;
reg oe;
reg [3:0] data_i;

// Outputs
wire [3:0] data_o;
wire [3:0] seq;

// Instantiate the Unit Under Test (UUT)
generator uut (
	.clk(clk), 
	.rst(rst), 
	.load(load), 
	.up(up), 
	.oe(oe), 
	.data_i(data_i), 
	.data_o(data_o), 
	.seq(seq)
);

initial begin
	// Initialize Inputs
	clk = 0;
	rst = 0;
	load = 0;
	up = 0;
	oe = 0;
	data_i = 0;

	// Wait 100 ns for global reset to finish
	#20;

	// Add stimulus here

end

always 
	#5  clk =  ! clk;



event reset_trigger; //объявление событий
event reset_done_trigger; //

//блок формирования Reset
initial begin 
	forever begin //бесконечный цикл 
	@ (reset_trigger); //ждем события reset_trigger
	@ (negedge clk); //ждем negedge clk
	rst = 1;    //сброс
	@ (negedge clk); 
	rst = 0; 
	-> reset_done_trigger; //сигналим что reset выполнен
	end 
end

//Ход симуляции
initial  
	begin: TEST_CASE 
		#10  -> reset_trigger;  //сделать ресет
	end

endmodule

Edited by Михей91

Share this post


Link to post
Share on other sites

Показал сегодня преподавателю все эти наработки, но он сказал что это можно использовать как дополнение к работе, т.к. саму работу нужно строить именно схемами, грубо говоря в файле .sch, каждый элемент из схемы на "рис. 1" нужно построить на отдельном листе.

CL-1 он обозначил за DEC, CL+1 за INC, сказал реализовать их как одноразрядный сумматор работающий в одну сторону, выглядит он так:

post-74572-1354277543_thumb.jpg

Но именно такой элемент я не нашел, есть предположение что нужно взять элемент XOR3 ?

 

Мультиплексор строим на элементе M2_1.

Регистры на FDP, FDC. Кстати их будет 16 штук, от 0 до F?

Буфер строим на BUFE.

 

Что касается того, что мы должны получить на временной диаграмме.

Нужно продемонстрировать направление счета: вверх, вниз и продемонстрировать загрузку, вот как это должно выглядеть:

post-74572-1354277535_thumb.jpg

 

Первая диаграмма демонстрирует направление счета, когда UP=1 мы плюсуем, как только UP=0 начинаем считать в обратную сторону.

Вторая диаграмма демонстрирует загрузку, тут я не совсем понял, мы должны задать только значение LOAD и на тот момент когда он включится DATA_I выберется само, или его тоже нужно определять руками?

Share this post


Link to post
Share on other sites

Scheme_1.sch

В ISE выбирай в колонке справа "Add Source"

Дальше выбираей Schematic

 

В открывшемся поле выбирай add symbol

 

Дальше по списку ищем компоненты, их есть там и сумматор и регистры. Не забудь добавить порты.

После этого свою схему включаешь в ISE

 

Цепляю файлик с компонентами к посту.

 

Гугли на тему "Xilinx ISE Schematic"

 

PS

Хотел пошутить про то, что это адовый изварт и схемным вводом ПЛИС делать это умом поехать, но потом вспомнил свой курсач на ту же тему, в котором мне не разрешили заменить задачу на К155 серии на ПЛИСовский и... Ох, хорошо, что кое где уже знают, что такие Xilinx и Verilog.

Share this post


Link to post
Share on other sites

Товарищи, и еще вопрос в догонку, реализовываю попутно автомат Мура:

post-74572-1354284555_thumb.jpg

 

и нужно данную комбинационную схему описать с помощью Case.

Уже все возможные варианты перепробовал, ругается на синтаксис...

 

`timescale 1ns / 1ps

module mur
(
	input wire           clk,
	input wire           rst,
	input wire           up,     
	output wire [3:0]    seq
);

//------------------------------------------
// SEQ using Case:
always @(posedge clk)
case (seq)

			4'h0:
				begin
					if (up == 0)
						4'h0 <= 4'h1;
					else (up == 1)
						4'h0 <= 4'hF;
				end

			//
			//все остальные значения
			//

			default:
				begin
					if (up == 0)
						4'hF <= 4'h0;
					else (up == 1)
						4'hF <= 4'hE;
				end

endcase
//------------------------------------------

endmodule

 

post-74572-1354284563_thumb.jpg

В зависимости от того, какое значение принимает UP мы движемся либо по часовой, либо против. Но в чем ошибка, не могу разобраться...

 

 

Muscat, ну как создать и цеплять схемотехнику слава богу я знаю))))) Сейчас посмотрю что прикрепили, и попытаюсь что-нибудь сделать ;)

Не хочет кушать схемку: Scheme_1.sch, Line 1 : Error : Parser fatal error encouted : An exception occurred! Type:UTFDataFormatException, Message:invalid byte 2 (я) of a 2-byte sequence. И я проект на Spartan3 создаю, а у Вас aspartan3a, это критично?

Edited by Михей91

Share this post


Link to post
Share on other sites

Показал сегодня преподавателю все эти наработки, но он сказал что это можно использовать как дополнение к работе, т.к. саму работу нужно строить именно схемами, грубо говоря в файле .sch, каждый элемент из схемы на "рис. 1" нужно построить на отдельном листе...

Ну и ну... Значит, таки прав был Muscat:

...Ну тогда по пути два.

Создаем модуль мультиплексор, модуль буфера, регистр и что там еще. Потом описываем их соединение, как вы делали это для элементов комбинационной логики...

В этом я Вам помочь не смогу, поскольку использую только продукцию Altera :laughing:

 

Товарищи, и еще вопрос в догонку, реализовываю попутно автомат Мура:

...

и нужно данную комбинационную схему описать с помощью Case.

Уже все возможные варианты перепробовал, ругается на синтаксис...

Еще бы. Присваиваете константу константе. Рекомендованную книгу Pong P. Chu не изучаете. :angry2: И советам не следуете:

Правильная мысль - нажать на лампочку в ISE и посмотреть примеры кода на Verilog. Там есть описания всех основных конструкций.

 

Mur.v

Share this post


Link to post
Share on other sites

Konst_777, ну на самом то деле преподаватель этот case на доске написал, вот только дома я повторил и получил то что получил, выходит он не компетентен или на шару нам на доске пишет?

 

А зачем нужен параметр: #(parameter BITS=4)?

Почему мы задаем именно так output reg [bITS-1:0] seq, а не [3:0]?

И в чем различие конструкций always @ от always @* ?

Почему мы пишем условие именно так if (up), без явного присвоения up`у нуля или единицы?

Edited by Михей91

Share this post


Link to post
Share on other sites

Попробуй вот так Scheme_1.sch

 

зачем нужен параметр: #(parameter BITS=4)?

Ох, Михей. Ты на программирование был? Паскал видель?

 

Это практически повсеместное правило, что разрядность шин задается через какой либо параметр (через generic или constant в VHDL или вот так в Verilog). Представь, что ты сделал счетчик на 4 разряда. Везде ручками написал [3:0]. В 10 местах так объявил. Или в 100, если проект большой. А потом пришел препод и сказал - а сделай ка Миха на 20 разрядов. И ты ручками начинаешь все переписывать. А так задал все порты через параметр, а потом по надобности меняешь его. Удобно же?

 

Почему мы пишем условие именно так if (up), без явного присвоения up`у нуля или единицы?

 

Потому что Верилог делали пацаны кодившие на Си (мир ему). Поэтому можно прмяо взять булево значние от сигнала (как от переменной в Си). То есть if(0) это false, a If (1), if(42) это true. В VHDL эта фича появилась только в последних ревизиях.

 

В Верилоге очень много таких штук, которые позволяют сократить объем кода и улучшить читаемость. С другой стороны эти "фичи" при невнимательном использовании позволяют оттяпать себе пальцы, от чего VHDL защищен.

 

Код с доски переписывать не стоит. Используй его только как ориентир, чтобы понять что он хочет.

 

Если не понимаешь, как что то делать, найди рабочий пример, выполни его и потом начинай понемногу модернизировать его в ту сторону, куда тебе надо. Это поможет избежать ситуации "ничего непонятно и ничего не работает".

 

Конечный автомат на Верлиог

http://www.altera.com/support/examples/ver...ver_statem.html

Share this post


Link to post
Share on other sites

Такой вопрос, как принудительно задать задержку на выполнения RST или UP?

По данной ссылке http://we.easyelectronics.ru/plis/testbenc...-novichkov.html задержка для RST задается с помощью события, но я не хочу городить такой же огород событий и для UP. Нельзя ли задать задержку более емко и компактно?

 

Разобрался: #30 up = 1; просто смутило то, что когда также описывал задержку для начала RST во временной диаграмме начало RST становилось красным...

 

Но появился еще один вопрос:

post-74572-1354371686_thumb.png

 

Разве у нас должен происходить счет, когда RST еще не запущен, ведь он является своего рода кнопкой пуска!? Как это исправить?

 

mur.v

`timescale 1ns / 1ps

module mur
  (
     input wire        clk,
     input wire        rst,
     input wire        up,
	output reg [3:0]  state,
     output reg [3:0]  seq
);

// Автомат Мура на 16 состояний

	// Объявление регистра состояний
	reg   [3:0] reg_state;

	// Объявление состояний
	localparam  S0 = 4'h0,  S1 = 4'h1,  S2 = 4'h2,  S3 = 4'h3,
					S4 = 4'h4,  S5 = 4'h5,  S6 = 4'h6,  S7 = 4'h7,
					S8 = 4'h8,  S9 = 4'h9,  SA = 4'hA,  SB = 4'hB,
					SC = 4'hC,  SD = 4'hD,  SE = 4'hE,  SF = 4'hF;
	// Объявление последовательности состояний
	localparam  STATE_0 = 4'h0,  STATE_1 = 4'h1,  STATE_2 = 4'h2,  STATE_3 = 4'h3,
					STATE_4 = 4'h4,  STATE_5 = 4'h5,  STATE_6 = 4'h6,  STATE_7 = 4'h7,
					STATE_8 = 4'h8,  STATE_9 = 4'h9,  STATE_A = 4'hA,  STATE_B = 4'hB,
					STATE_C = 4'hC,  STATE_D = 4'hD,  STATE_E = 4'hE,  STATE_F = 4'hF;
	// Объявление выходных значений по последовательности состояний согласно варианту
	localparam  SEQ_0 = 4'hF,  SEQ_1 = 4'h8,  SEQ_2 = 4'h7,  SEQ_3 = 4'h0,
					SEQ_4 = 4'h5,  SEQ_5 = 4'h2,  SEQ_6 = 4'hC,  SEQ_7 = 4'hB,
					SEQ_8 = 4'h4,  SEQ_9 = 4'h3,  SEQ_A = 4'hE,  SEQ_B = 4'h9,
					SEQ_C = 4'h6,  SEQ_D = 4'h1,  SEQ_E = 4'hD,  SEQ_F = 4'hA;  						

	// SEQ зависит только от одного конкретного состояния
	always @* begin
		case (reg_state)
			S0:
			begin
				state = STATE_0;
				seq = SEQ_0;
			end
			S1:
			begin
				state = STATE_1;
				seq = SEQ_1;
				end
			S2:
			begin
				state = STATE_2;
				seq = SEQ_2;
				end
			S3:
			begin
				state = STATE_3;
				seq = SEQ_3;
				end
			S4:
			begin
				state = STATE_4;
				seq = SEQ_4;
				end
			S5:
			begin
				state = STATE_5;
				seq = SEQ_5;
				end
			S6:
			begin
				state = STATE_6;
				seq = SEQ_6;
				end
			S7:
			begin
				state = STATE_7;
				seq = SEQ_7;
				end
			S8:
			begin
				state = STATE_8;
				seq = SEQ_8;
				end
			S9:
			begin
				state = STATE_9;
				seq = SEQ_9;
				end
			SA:
			begin
				state = STATE_A;
				seq = SEQ_A;
				end
			SB:
			begin
				state = STATE_B;
				seq = SEQ_B;
				end
			SC:
			begin
				state = STATE_C;
				seq = SEQ_C;
				end
			SD:
			begin
				state = STATE_D;
				seq = SEQ_D; 
				end
			SE:
			begin
				state = STATE_E;
				seq = SEQ_E; 
				end
			SF:
			begin
				state = STATE_F;
				seq = SEQ_F; 
				end
			default:
			begin
				state = STATE_0;
				seq = SEQ_0;
				end
		endcase
	end

	// Определение следующего состояния
	always @ (posedge clk, posedge rst) begin
		if (rst)
			reg_state <= S0;
		else
			case (reg_state)
				S0:
					if (up)
						reg_state <= S1;
					else
						reg_state <= SF;
				S1:
					if (up)
						reg_state <= S2;
					else
						reg_state <= S0;
				S2:
					if (up)
						reg_state <= S3;
					else
						reg_state <= S1;
				S3:
					if (up)
						reg_state <= S4;
					else
						reg_state <= S2;
				S4:
					if (up)
						reg_state <= S5;
					else
						reg_state <= S3;
				S5:
					if (up)
						reg_state <= S6;
					else
						reg_state <= S4;
				S6:
					if (up)
						reg_state <= S7;
					else
						reg_state <= S5;
				S7:
					if (up)
						reg_state <= S8;
					else
						reg_state <= S6;
				S8:
					if (up)
						reg_state <= S9;
					else
						reg_state <= S7;
				S9:
					if (up)
						reg_state <= SA;
					else
						reg_state <= S8;
				SA:
					if (up)
						reg_state <= SB;
					else
						reg_state <= S9;
				SB:
					if (up)
						reg_state <= SC;
					else
						reg_state <= SA;
				SC:
					if (up)
						reg_state <= SD;
					else
						reg_state <= SB;
				SD:
					if (up)
						reg_state <= SE;
					else
						reg_state <= SC;
				SE:
					if (up)
						reg_state <= SF;
					else
						reg_state <= SD;
				SF:
					if (up)
						reg_state <= S0;
					else
						reg_state <= SE;
				default:   
						reg_state <= S0;               
			endcase
	end

endmodule // mur

 

mur_tb.v

`timescale 1ns / 1ps

module mur_tb;

// Inputs
reg clk;
reg rst;
reg up;

// Outputs
wire [3:0] state;
wire [3:0] seq;

// Instantiate the Unit Under Test (UUT)
mur uut (
	.clk(clk), 
	.rst(rst), 
	.up(up),
	.state(state),
	.seq(seq)
);

initial begin
	// Initialize Inputs
	clk = 0;
	rst = 0;
	up = 0;

	// Wait 20 ns for global reset to finish
	#20;
end

// Cоздание CLK 
always 
	#5  clk =  ! clk; 

// Cоздание RST 
	// Объявление событий
	event rst_trigger; //вызывается, когда нам необходимо выполнить RST
	event rst_done_trigger; //сообщает что RST выполнен

	// Блок формирования RST
	initial begin 
		forever begin //бесконечный цикл 
			@ (rst_trigger); //ждем события rst_trigger
			@ (negedge clk); //ждем negedge CLK
			rst = 1;    
			//сброс
			@ (negedge clk); 
			rst = 0; 
			-> rst_done_trigger; //сигналим что RST выполнен
		end 
	end

   // Ход симуляции
initial 
	begin
	#20  -> rst_trigger;  //выполнить RST с задержкой 20нс
	@ (rst_done_trigger); //ждем сигнал о завершении RST
	@ (negedge clk);      
		#10 up = 1; 
	repeat (10)
		begin  //цикл на 10 повторений
			@ (negedge clk); //ждем negedge CLK
		end 
	up = 0;
end

endmodule

 

RST включается после того, как CLK переходит из логической 1 в логический 0 (negende), но когда я задаю задержку для RST в 20нс, то на временной диаграмме, в самом начале пока CLK не упал счет отсутствует, что верно, а когда срабатывает условие negende и начинается задержка, то счет начинается, получается что он не видит эту задержку и не реагирует на нее? Хотя задержка UP на счет не повлияла, он все правильно считает...

Edited by Михей91

Share this post


Link to post
Share on other sites

>>Разве у нас должен происходить счет, когда RST еще не запущен, ведь он является своего рода кнопкой пуска!?

Читай код, там все написано.

RST является сигналом сброса, а не пуска. У тебя есть процесс, который сидит в always. Он выполняется либо по фронту клока либо по фронту резета. По клоку он выполняет счет, по резету сброс. Это не я так решил, у тебя так написано. В отсутствии резета он идет по ветке if(rst=1) else и там дальше встречает case и у тебя и идет счет.

Почему он не должен идти в case, пока нет резета? Нет причин не идти в case.

 

Если хочешь, чтобы резет был пуском, то добавь некое состояние wait, в котором автомат будет находится по умолчанию и ничего не делать, пока не придет сигнал запуска.

 

Рекомендую все таки вдумчиво выполнить пример с изи-элекроник, осмыслить код, понять что это код делает, помоделировать его и делать свое. Никакого огорода там нет.

Share this post


Link to post
Share on other sites

if (reset == 1'b1) begin

count <= 0;

end else if ( enable == 1'b1) begin

count <= count + 1;

end

 

1) Красное, это состояние Х. Физически его не существует, но это удобно при симуляции для ловли багов. Если ты прибавляешь к Х что нибудь, получишь все равно Х. Поэтому вначале долго идет Х. пока ничего не сброшено.

2) Затем приходит резет и сбрасывает счетчик в 0. И стоит в нуле. Недолго, всего 1 такт.

3) На следующем такте резета уже нет, но становится активен сигнал enable. А if enable=1 то клацаем счетчик. Убери енабле и счетчик так и будет стоять в 0.

Share this post


Link to post
Share on other sites

Muscat, спасибо, с автоматом мура покончено, разобрал все что можно, на временной диаграмме все показал. Если кому нужен проект, могу скинуть. Перехожу к реверсивному счетчику...

Share this post


Link to post
Share on other sites

Насчет CL-1 и CL+1, не понял как построить их на XOR3, когда нам нужны два выхода СО и О, СО пойдет на CI выше стоящего, тогда куда пойдет СО самого верхнего?

На вход А мы подаем Q (текущее состояние), а В мы должны подобрать так, чтобы реализовывалась функция сложения или вычитания, вот например когда на входы A устройства DEC мы подаем 0000 то чтобы происходил вычет, на В мы должны подать 1111, и на выходе О получаем 1111, что верно из 0 в F, а для INC B = 1110. Но стоит лишь поменять значение Q при таких же В, так на выходе получается уже не то что надо...

 

Мультиплексоры вроде нарисовал...

 

Регистры на FDP, FDC. Зачем мне нужен у FDP вход PRE, что с ним делать... И до сих пор не могу понять сколько мне нужно регистров? 16 штук от 0 до F или же 4 штуки что соответствует 4 разрядам числа...

 

Буфер BUFE. Данный элемент я тоже не нашел, использовать BUFGCE?

Но там Clock enable input обозначен как СЕ, мне просто на него маркер поставить со своим обозначение, т.е. OE и ничего страшного?

 

Нарисовал на одном листе мультиплексоры, на выход установил маркер Q_NXT, на другом листе нарисовал регистр, и на вход регистра, согласно схеме, нужно подать Q_NXT с мультиплексора, ставлю маркер, пишу такое же имя, а он мне выдает ошибку мол данное имя уже занято, сделайте другое... вот не понимаю, как тогда мне связать элементы на разных листах?

 

revers_sch.sch

Share this post


Link to post
Share on other sites

Продвинулся дальше.

 

Выкладываю для критики: revers_sch.sch

 

1 лист. Так и не понял как быть со значениями B у ADSU4, в мануалы и лампочки не пинайте я там все посмотрел.

 

3 лист. У FDC таблица логики такая:

CLR|D|C|Q

1|X|X|0

0|D|?|D

а у FDP такая:

PRE|C|D|Q

1|X|X|1

0|?|D|D

По факту отличия идут когда CLR и PRE принимают состояние логической единицы, правильно что я поставил инвентор перед PRE, чтобы получать одинаковые выходные значения?

 

4 лист. На третьем листе мы получили выходы Q[0...3] как мне теперь их объединить в одно целое чтобы подать все на один элемент тристабильного буфера?

 

P.S. наверное я всех достал, приношу свои извинения, ну еще немножко осталось, истина близка)

Edited by Михей91

Share this post


Link to post
Share on other sites

Нет, без RTFM к сожалению не получится. Надо все таки read этот FM.

 

 

>>1)1 лист. Так и не понял как быть со значениями B у ADSU4, в мануалы и лампочки не пинайте я там все посмотрел.

ABDUS4 это полный сумматор. На один порт ты подал сигнал Q, молодец. Теперь подумай с чем ты его складываешь и что надо подать на порт B. И зачем тебе 2 сумматора.

 

FDP и FDC это триггеры со сбросом (порт CLR) и с предустановкой в 1 (порт PRE). По получению '1' в этот порт (вроде вход не инверсный) они выполнят соответствующие операции (сброс или предустановка). Инвертор приведет к тому, что у тебя FDC триггеры будут сбрасываться по одному уровню RST, а FDP по другому (ты же инвертор поставил). Подумай, этого ли ты хотел. И зачем 2 разных типа триггеров.

 

 

>> как мне теперь их объединить в одно целое чтобы подать все на один элемент тристабильного буфера?

Один элемент буфера имеет 1 вход. 3 входа в один не впихнуть. Не знаю, как это делается схемотехнически, но думаю, что тебе нужно либо найди буфер, у которого вход будет шиной, либо поставить 4 отдельных буфера, а потом выходы их завести на общую шину.

 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...