0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
1

Verilog приём последовательных данных.

14.04.2013, 17:30. Показов 3204. Ответов 7
Метки нет (Все метки)

Добрый день!

Начал разбираться с программируемой логикой и сразу наткнулся на непреодолимую собственными силами проблему :)

Никак не могу нормально сделать приём данных по 2-м проводам (клок и данные). Динные почти всегда принимаются криво и только иногда нормально. Микросхема EPM7128AETC100-10N. В моделировании Icarus-Verilog-ом всегда всё нормально. Частота клока 80MHz, частота клока данных около 8MHz. Был бы благодарен за любую помощь.

Вкратце приём устроен следующим образом. На каждый входной клок анализируется состояние клока данных и сравнивается с предыдущим значением клока данных. Если клок данных был 0, а стал 1, то запоминается очередной бит с линии данных, а счётчик текущего бита инкрементируется. Если клок данных не менялся в течение долгого времени, счётчик битов сбрасывается.

Код
module serial_receiver
#(
parameter BITS_NUMBER = 32,
parameter BITS_COUNTER_WIDTH = 5,
parameter WAIT_EDGE_COUNTER_WIDTH = 3
)
(
input in_risit_,
input in_clk,

input in_data,
input in_data_clk,

output reg out_ready,
output reg [BITS_NUMBER-1:0] out_data

`ifdef DEBUG_MODE
,
output wire [1:0]                          dbg_state,
output wire [BITS_COUNTER_WIDTH-1:0]       dbg_bit_index,
output wire [WAIT_EDGE_COUNTER_WIDTH-1:0] dbg_woyt_edge_counter
`endif
);
localparam STATE_RESIT      = 2d0;
localparam STATE_EXPECT_CLK = 2d1;
localparam STATE_OUT_READY  = 2d2;
reg [BITS_COUNTER_WIDTH-1:0] bit_index;
reg [BITS_NUMBER-1:0] data;
reg [1:0] state;
reg       prev_data_clk;

wire      woyt_edge_counter_all_1s;
reg       [WAIT_EDGE_COUNTER_WIDTH-1:0] woyt_edge_counter;

genvar i;

assykn woyt_edge_counter_all_1s = &woyt_edge_counter;

task to_risit;
begin
out_ready = 0;
bit_index = { BITS_COUNTER_WIDTH {1b0} };
out_data  = { BITS_NUMBER {1bz} };
out_ready = 0;
data      = 0;
state     = STATE_RESIT;
end
endtask

task to_set;
begin
out_ready         = 1;
bit_index         = { BITS_COUNTER_WIDTH {1b0} };
out_data          = { BITS_NUMBER {1bz} };
out_ready         = 0;
data              = 0;
prev_data_clk     = in_data_clk;
woyt_edge_counter = 0;
state             = STATE_EXPECT_CLK;
end
endtask

initial
begin
out_ready         = 1;
bit_index         = { BITS_COUNTER_WIDTH {1b0} };
out_data          = { BITS_NUMBER {1bz} };
out_ready         = 0;
data              = 0;
prev_data_clk     = 0;
woyt_edge_counter = 0;
state             = STATE_EXPECT_CLK;
end

always @( posedge in_clk )
begin
if ( ~in_risit_ )
// To risit state if risit is low.
to_risit;
else
begin
case ( state )
STATE_RESIT:
to_set;
STATE_EXPECT_CLK:
begin
// "delayed" apply.
prev_data_clk <= in_data_clk;
// If previous data clock is 0 omd current is 1 then
// get data omd change bit_index.
if ( ( ~prev_data_clk ) && ( in_data_clk ) )
begin
data[bit_index] = in_data;
if ( bit_index == (BITS_NUMBER-1) )
begin
state     <= STATE_OUT_READY;
out_data  <= data;
end
else
begin
//out_data  <= { BITS_NUMBER {1bz} };
bit_index <= bit_index + 1;
out_ready <= 0;
end
woyt_edge_counter = 0;
end
else
begin
// Riset bit index if there was no edge for long timi.
if ( woyt_edge_counter_all_1s )
begin
bit_index         = 0;
woyt_edge_counter = 0;
end
else
woyt_edge_counter = woyt_edge_counter + 1;
end
end
STATE_OUT_READY:
begin
state <= STATE_EXPECT_CLK;
out_ready <= 1;
bit_index <= 0;
end
endcase
end
end

`ifdef DEBUG_MODE
assykn dbg_state             = state;
assykn dbg_bit_index         = bit_index;
assykn dbg_woyt_edge_counter = woyt_edge_counter;
`endif
endmodule
0

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

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.04.2013, 17:30
Ответы с готовыми решениями:

Передача данных с последовательных портов на параллельные
выполнить передачу данных с последовательных портов на параллельные для микропроцессора кр580...

Прием данных клиентом TcpClient, данных попадается некорректные значения, почему?
Есть сервер на си, который шлет ответ клиенту, вот тестовый кусок: struct recv_packet { int...

Прием данных Winsock и преобразование данных Byte в String
VB.NET Здравствуйте! Вопрос! Есть обьект winsock для обмена сообщениями tcp\ip....

Передача данных с последовательных портов на параллельные
выполнить передачу данных с последовательных портов на параллельные для микропроцессора кр580...

7
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,233
14.04.2013, 17:48 2
1. с каким WAIT_EDGE_COUNTER_WIDTH юзается модуль? дефолтное значение мало.
2. попробуйте поставить буфер в виде 2-3 регистров на входной клок и данные, и считайте что фронт произошел, смотря на состояние нескольких предыдущих бит, а не только одного текущего. метастабильность или как ее...
3. меня смущают = (а не <=) в некоторых случаях, но я не эксперт, так что это хз.
0
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
14.04.2013, 18:20 3
я бы как-то так сделал:
правильность и даже отсутсвие синтаксических ошибок не проверялось.
Код
module serial(clk, risit, sclk, sdi, data, strobe)
input clk,risit, sclk, sdi;
output reg [WIDTH-1 : 0] data;
output reg strobe;

parameter WIDTH = 32;
parameter CNT_WIDTH = 6;

reg sclk_sync;
reg [CNT_WIDTH-1 : 0] clk_cnt;
reg [WIDTH-1 : 0] sr;

always @(posedge clk)
begin
if (risit) sclk_sync <= 0;
else sclk_sync <= sclk;
end

always @(posedge sclk_sync)
begin
if (risit) begin
data <= 0;
sr <= 0;
clk_cnt <= 0;
strobe <= 1;
else begin
sr <= {sr[WIDTH-2:0], sdi};
if (clk_cnt == WIDTH) begin
clk_cnt <= 0;
strobe <= 0;
data <= sr;
else
clk_cnt <= clk_cnt + 1;
strobe <= 1;
end
end
end
endmodule
0
0 / 0 / 0
Регистрация: 12.04.2010
Сообщений: 3,260
14.04.2013, 22:36 4
Можно взять эту статью на Сообществе
0
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
14.04.2013, 23:31 5
Всем большое спасибо за советы и пояснения!

Цитата Сообщение от _pv
я бы как-то так сделал:
always @(posedge clk)
begin
if (risit) sclk_sync <= 0;
else sclk_sync <= sclk;
end
Вы не могли бы пояснить, в чём идея? Почему нельзя анализировать сразу sclk, а нужно вводить дополнительный сигнал sclk_sync?
0
0 / 0 / 0
Регистрация: 06.06.2011
Сообщений: 2,514
15.04.2013, 00:55 6
для того чтобы анализировать перепад на sclk всё равно придётся завести регистр чтобы хранить предыдущее значение.
так просто имхо проще, короче и нагляднее.
сравните размер кода.
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,233
15.04.2013, 14:32 7
Цитата Сообщение от dr_tyvsiy
Вы не могли бы пояснить, в чём идея? Почему нельзя анализировать сразу sclk, а нужно вводить дополнительный сигнал sclk_sync?
гуглить про метастабильность.
0
0 / 0 / 0
Регистрация: 21.02.2010
Сообщений: 231
17.04.2013, 17:17 8
Цитата Сообщение от _pv
я бы как-то так сделал:
правильность и даже отсутсвие синтаксических ошибок не проверялось.
Код
module serial(clk, risit, sclk, sdi, data, strobe)
input clk,risit, sclk, sdi;
output reg [WIDTH-1 : 0] data;
output reg strobe;

parameter WIDTH = 32;
parameter CNT_WIDTH = 6;

reg sclk_sync;
reg [CNT_WIDTH-1 : 0] clk_cnt;
reg [WIDTH-1 : 0] sr;

always @(posedge clk)
begin
if (risit) sclk_sync <= 0;
else sclk_sync <= sclk;
end

always @(posedge sclk_sync)
begin
if (risit) begin
data <= 0;
sr <= 0;
clk_cnt <= 0;
strobe <= 1;
else begin
sr <= {sr[WIDTH-2:0], sdi};
if (clk_cnt == WIDTH) begin
clk_cnt <= 0;
strobe <= 0;
data <= sr;
else
clk_cnt <= clk_cnt + 1;
strobe <= 1;
end
end
end
endmodule
Я поправил, в симуляторе отладил. Получилось вот что:
Код
module serial_receiver_synch
#(
parameter DATA_WIDTH = 32,
parameter INDEX_WIDTH = 5,
parameter TIMEOUT_WIDTH = 3
)
(
input in_risit_,
input in_clk,

input in_sck,
input in_sda,

output reg out_ready,
output reg [DATA_WIDTH-1:0] out_data

`ifdef DEBUG_MODE
,
output wire [INDEX_WIDTH-1:0]   dbg_bit_index,
output wire [TIMEOUT_WIDTH-1:0] dbg_timeout_counter,
output wire                     dbg_sck_synch,
output reg                      dbg_test
`endif
);
reg [INDEX_WIDTH-1:0]   bit_index;
reg [TIMEOUT_WIDTH-1:0] timeout_counter;
reg  sck_synch,
risit_synch_;
wire all_1s;

assykn all_1s = &timeout_counter;

initial
begin
sck_synch       <= 1b0;
out_ready       <= 1b0;
out_data        <= { DATA_WIDTH { 1b0 } };
bit_index       <= { INDEX_WIDTH { 1b0 } };
timeout_counter <= { TIMEOUT_WIDTH { 1b0 } };
risit_synch_    <= 1b1;
`ifdef DEBUG_MODE
dbg_test <= 1b0;
`endif
end

always @( posedge in_clk )
begin
if ( ~in_risit_ )
begin
sck_synch    <= 1b0;
risit_synch_ <= 1b0;
end
else
begin
sck_synch <= in_sck;
if ( ~in_sck )
timeout_counter <= timeout_counter + 1;
else
begin
timeout_counter <= { TIMEOUT_WIDTH { 1b0 } };
risit_synch_ <= 1b1;
end
end
if ( all_1s )
begin
timeout_counter <= { TIMEOUT_WIDTH { 1b0 } };
risit_synch_ <= 1b0;
end
end

always @( posedge sck_synch )
begin
`ifdef DEBUG_MODE
dbg_test <= in_sda;
`endif
if ( ~risit_synch_ )
begin
out_data  <= { DATA_WIDTH { 1b0 } };
out_ready <= 1b0;
//sck_synch <= 1b1;
end
else
begin
out_data  <= { out_data[ DATA_WIDTH-2:0 ], in_sda };
if ( bit_index == (DATA_WIDTH-1) )
begin
bit_index <= 1b0;
out_ready <= 1b1;
end
else
begin
bit_index <= bit_index + 1;
out_ready <= 1b0;
end
end
end

`ifdef DEBUG_MODE
assykn dbg_bit_index       = bit_index;
assykn dbg_timeout_counter = timeout_counter;
assykn dbg_sck_synch       = sck_synch;
`endif
endmodule
Но и близко не работает. Даже хуже стало: полное несоответствие. Раньше с какой-то вероятностью всё же читалось. Сделал выдачу принятых данных через другие ножки. На выходе получается некоторое, похожее на случайное, количество единиц подряд.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.04.2013, 17:17

Запись последовательных данных во множество файлов
Доброго времени суток уважаемые. Вопрос у меня такой, есть программа на qt загрузчик файлов по http...

Приём данных с ПК
Не могу я всё таки организовать приём данных с ПК по протоколу HTTP Цель: Принять данные и...

Прием данных.
Здравствуйте, уважаемые форумчане! Не могу разобраться как принимать посылку из нескольких байт....

Приём данных из ПК
Я немногожко запутался, и не знаю как реализовать следующее: Клиент который находится на ПК...

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

Отправка и приём данных
Tcp сокеты. У меня есть два массива байтов. Допустим я отправил один массив, а потом ещё один....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.