Мне нужно разработать инфракрасный передатчик с использованием FPGA и Verilog.
Одним из условий является отправка пакета каждые 10 Гц, у меня есть счетчик, который создает вторичные часы на частоте 10 Гц от основных часов (100 МГц). Пакет содержит Start-Gap-Select-Gap-Right-Gap-Left-Gap-Forward-Gap-Backwards-Gap. У меня есть FSM, который выполняет этот переход на положительном фронте вторичного тактового сигнала 10 Гц. Каждый из этих блоков в пакете имеет свой размер, а Gap — это просто пустое пространство, которое их разделяет. Блоки направления имеют больший размер при выборе и меньший в противном случае. При условии, что приемник имеет частоту импульсов 36 кГц, у меня есть еще один счетчик, который уменьшает основные часы до 36 кГц, которые я использую для генерации размеров импульсов для запуска, выбора и т. Д. И делаю выходной светодиод 1, в то время как счетчик считает до этот размер (для запуска случаев выберите ..) и 0 для состояния разрыва.
Однако, когда я смотрю на светодиод через камеру своего смартфона, он показывает, что он включен все время, что я и ожидаю увидеть, поскольку он должен отправлять пакеты 10 раз в секунду.
Проблема в том, что машина вообще не двигается, мой вопрос в том, это правильная логика действий или я что-то упускаю? Спасибо
Запрашиваемый код:
Счетчик для импульса 36 кГц
always@(posedge CLK) begin
if(RESET) begin
Counter <= 0;
SEC_CLK <= 0;
end
else if(Counter == 2778) begin
Counter <= 0;
SEC_CLK <= 1'b1;
end
else begin
Counter <= Counter + 1;
SEC_CLK <= 1'b0;
end
end
Счетчик 10 Гц, не знаю, хорошо ли уменьшить 36 кГц или использовать Master Clock, но это хорошее круглое число, поэтому я использовал Master Clock.
always@(posedge CLK) begin
if(sec_counter == 100000) begin
sec_counter <= 0;
send <= 1;
end
else begin
sec_counter <= sec_counter +1;
send <= 0;
end
end`
Логика конечного автомата:
always@(Curr_State) begin
case(Curr_State)
1'd0: begin //START
Next_State <= 1'd1;
Previous_State <= Next_State;
max_count <= StartBurstSize;
flag <= 0;
end
1'd1: begin //GAP
if(Previous_State <= 1'd7)
Next_State<=1'd0;
else
Next_State <= Previous_State +1;
max_count <= GapSize;
flag <= 1;
IR_LED = 1'b1;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
end
1'd2: begin //SELECT
Next_State <= 1'd1;
Previous_State <= Curr_State;
max_count <= CarSelectBurstSize;
IR_LED = 1'b0;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
end
1'd3: begin //RIGHT
if(BTNR)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
1'd4: begin //LEFT
if(BTNL)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
1'd5: begin //FORWARD
if(BTNU)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
1'd6: begin //Backwards
if(BTND)
max_count <= AsserBurstSize;
else
max_count <= DeAssertBurstSize;
Next_State <= 1'd1;
Previous_State <= Curr_State;
flag <= 0;
if(change)
Curr_State <= Next_State;
else
Next_State <= Curr_State;
IR_LED = 1'b1;
end
endcase
end
ПОСЫЛКА ИМПУЛЬСОВ НА ИК-СВЕТОДИОД
always@(posedge SEC_CLK) begin
if(send) begin
if(Pcounter == max_count) begin //COUNTING BLOCK SIZE
Pcounter <= 0;
IR_LED=1'b0;
end
else begin
if(flag)
IR_LED=1'b0; //GAP
else
IR_LED=1'b1;
Pcounter <= Pcounter+1;
end
end
end