Как работать с асинхронными сигналами (камера - внешняя память)
Verilog-2001, QuartusII 13.0. Необходимо с камеры записать информацию во внешнюю sram память.
Имеются модули: CameraGrab (Захват данных с камеры), SRAM_Module (Запись/чтение SRAM), MainController (Контроллер), Main (Модуль верхнего уровня).
Для примера убрал все лишнее из модулей, что бы не нагромождать, постарался оставить так, что бы было понятно что примерно каждый из модулей делает: Модуль верхнего уровня Main:
module Main(
input wire clk_24MHz,
input wire clk_100MHz,
output wire [7:0] o_SramData8OUT,
output wire o_DataValid
);
wire w_CamValidPix;
wire [7:0] w_camData8;
wire w_SramEn;
wire [7:0] w_SramData8;
wire w_SramBusy;
wire w_SramDone;
MainController MC(
.clk_24MHz(clk_24MHz),
.clk_100MHz(clk_100MHz),
.i_CamValidPix(w_CamValidPix),
.i_camData8(w_camData8),
.i_SramBusy(w_SramBusy),
.i_SramDone(w_SramDone),
.o_SramEn(w_SramEn),
.o_SramData8(w_SramData8)
);
SRAM_Module SM(
.clk_100MHz(clk_100MHz),
.i_SramEn(w_SramEn),
.i_SramData8(w_SramData8),
.o_SramBusy(w_SramBusy),
.o_SramDone(w_SramDone),
.o_SramData8OUT(o_SramData8OUT),
.o_DataValid(o_DataValid)
);
CameraGrab CG(
.clk_24MHz(clk_24MHz),
.o_CamValidPix(w_CamValidPix),
.or_camData8(w_camData8)
);
endmodule
Модуль контроллера (обработчика). Суть вопроса именно в нем MainController:
module MainController (
input wire clk_24MHz,
input wire clk_100MHz,
input wire i_CamValidPix,
input wire [7:0] i_camData8,
input wire i_SramBusy,
input wire i_SramDone,
output reg o_SramEn,
output wire [7:0] o_SramData8
);
//здесь главный вопрос...
//по сигналу i_CamValidPix надо передать один раз данные в SRAM_Module
//т.е. разрешить передачу байта и вовремя запретить, что бы не передать его дважды
always @ (posedge i_CamValidPix) begin
if (!i_SramBusy && i_CamValidPix) o_SramEn <= 1'd1; //разрешаем передачу...
//..тут не понимаю как быть дальше. надо o_SramEn как-то отключить как только модуль SRAM_Module его принял в работу
end
//передаем байт в модуль SRAM_Module непрерывно как есть
assign o_SramData8 = i_camData8;
endmodule
Модуль захвата с камеры CameraGrab:
module CameraGrab (
input wire clk_24MHz,
output wire o_CamValidPix,
output reg [7:0] or_camData8
);
reg r_change = 1'd0;
//для примера - меняем выходные данные при каждом клоке
always @ (posedge clk_24MHz) begin
r_change <= !r_change;
if (r_change) or_camData8 <= 8'd0;
else or_camData8 <= 8'd255;
end
//как пример валидности данных - просто выводим входной клок
assign o_CamValidPix = clk_24MHz;
endmodule
Модуль записи во внешнюю память SRAM_Module:
module SRAM_Module (
input wire clk_100MHz,
input wire i_SramEn,
input wire [7:0] i_SramData8,
output reg o_SramBusy = 1'd0,
output reg o_SramDone = 1'd0,
output reg [7:0] o_SramData8OUT,
output reg o_DataValid
);
reg [3:0] state = 4'd0;
always @ (posedge clk_100MHz) begin
case (state)
4'd0: begin
o_SramDone <= 1'd0; //не закончено
//если сигнал разрешения
if (i_SramEn) begin
o_SramBusy <= 1'd1; //занят
//отправляем полученные от модуля камеры данные наружу
o_SramData8OUT <= i_SramData8;
o_DataValid <= 1'd1;
state <= 4'd1; //переход
end
else begin
state <= 4'd0; //остаемся здесь
end
end
4'd1: begin
//что-то еще делаем
o_DataValid <= 1'd0;
state <= 4'd2; //переход
end
4'd2: begin
o_SramBusy <= 1'd0; //свободен
o_SramDone <= 1'd1; //закончено
state <= 4'd0; //переход в начало
end
default: begin
state <= 4'd0;
end
endcase
end
endmodule
CameraGrab на частоте 24МГц принимает байты с физического устройства и передает в MainController сигнал валидности данных, т.е. по фронту этого сигнала можно записывать байт в память. SRAM_Module работает на частоте 100МГц и за 3 такта производит запись в микросхему SRAM.
Не могу понять как в модуле обработчика MainController правильно передать байт с камеры по сигналу валидности (фронт сигнала от CameraGrab) в SRAM_Module. Возможно, надо как-то экранировать и сбрасывать сигнал готовности данных (что бы не писать одни и те же данные дважды). Но как это сделать, что бы не трогать сам входной сигнал, а оперировать экранированным? По сути надо поймать сигнал готовности данных (24МГц) и по его фронту один раз запустить конечный автомат (100МГц), далее снова ожидать фронт сигнала готовности данных...
Желательно без использования fifo и других буферов, ведь камера передает данные на гораздо меньшей частоте и мы успеваем записать данные в память до того как придет следующий валидный байт. Я новичок, прошу направить в правильное русло.