Перейти к содержанию
    

Конфигурируемый приемник RS-232

Всем, привет. Сразу скажу, что в проектировании на ПЛИС я полный 0. Но выпала такая потребность (для учебы) создать приемник rs 232. Посмотрел много всего, но так и не разобрался и ни один код не заработал. Требуемые параметры 16 МГц Скорости 57600 и 115200,  Бит четности Odd 6. Может кто направить или подсказать с чего начать делать? Возможно у кого-то есть свои наработки. Язык использую Verilog.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, lyaksandrov сказал:

Всем, привет. Сразу скажу, что в проектировании на ПЛИС я полный 0. Но выпала такая потребность (для учебы) создать приемник rs 232. Посмотрел много всего, но так и не разобрался и ни один код не заработал. Требуемые параметры 16 МГц Скорости 57600 и 115200,  Бит четности Odd 6. Может кто направить или подсказать с чего начать делать? Возможно у кого-то есть свои наработки. Язык использую Verilog.

В учебнике Тарасова этот проект есть на vhdl.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

my_work_loopback.zip

в uart.vhd 

entity UART is
    Generic (
        CLK_FREQ      : integer := 50e6;   -- system clock frequency in Hz
        BAUD_RATE     : integer := 115200; -- baud rate value
        PARITY_BIT    : string  := "none"; -- type of parity: "none", "even", "odd", "mark", "space"
        USE_DEBOUNCER : boolean := True    -- enable/disable debouncer
    );

пропишите свою тактовую частоту и другие параметры UART...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

04.05.2022 в 18:33, lyaksandrov сказал:

 Может кто направить или подсказать с чего начать делать? Возможно у кого-то есть свои наработки. Язык использую Verilog.

Начните со своего проекта. Уверяю, у Вас получиться лучше, чем у Тарасова.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мой параметризируемый модуль приемника UART:
https://github.com/DigitalRabbit85/SvLibDR/tree/main/SingleRxUART
За пояснениями - в личку...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

04.05.2022 в 18:33, lyaksandrov сказал:

Всем, привет. Сразу скажу, что в проектировании на ПЛИС я полный 0. Но выпала такая потребность (для учебы) создать приемник rs 232. Посмотрел много всего, но так и не разобрался и ни один код не заработал. Требуемые параметры 16 МГц Скорости 57600 и 115200,  Бит четности Odd 6. Может кто направить или подсказать с чего начать делать? Возможно у кого-то есть свои наработки. Язык использую Verilog.

Если и хотите остаться нулем в ПЛИС - то используйте чужие наработки. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

05.05.2022 в 19:54, sazh сказал:

Начните со своего проекта. Уверяю, у Вас получиться лучше, чем у Тарасова.

У Тарасова меньше ресурсов ПЛИС уходит. Можно на мелкой CPLD сделать. Там только делитель тактовой включать/отключать придётся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

со скоростью 115200

1) без 8-кратного оверсемплинга на приеме

2) без выхода из зависшего состояния по 11 стоп-битам

3) без FIFO минимум на 16 байт

в реальной жизни работать невозможно

и неважно что там влезает или нет в CPLD

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 минуты назад, krux сказал:

в реальной жизни работать невозможно

и неважно что там влезает или нет в CPLD

Это же для учебы, не для устройства.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 5/4/2022 at 6:33 PM, lyaksandrov said:

Всем, привет. Сразу скажу, что в проектировании на ПЛИС я полный 0. Но выпала такая потребность (для учебы) создать приемник rs 232. Посмотрел много всего, но так и не разобрался и ни один код не заработал. Требуемые параметры 16 МГц Скорости 57600 и 115200,  Бит четности Odd 6. Может кто направить или подсказать с чего начать делать? Возможно у кого-то есть свои наработки. Язык использую Verilog.

Вот Вам мои полностью рабочие UART.

Описание сигналов (передатчик):

// clock
input clk, - опорный тактовый сигнал
// reset
input reset, - синхронный сброс
// control
input [15:0] UBRR, - делитель скорости UART (нужно записывать число на 1 меньше требуемого значения)
input [3:0] UBW, - количество семплов на один бит (нужно записывать число на 1 меньше требуемого значения)
input [3:0] num_bit, - количество бит (нужно записывать число на 1 меньше требуемого значения)
input USBS, - 2 стоп-бита
// data
input WR, - строб записи
input [7:0] TXB, - данные
input TXB8, - данные, 9 бит
// TXD
output TXD, - выход передатчика
// flag
input CLR_TXC, - сброс флага TXC
output reg TXC, - флаг завершения передачи
output UDRE, - флаг опустошения буфера передатчика
output DE - управление драйвером RS485

Описание сигналов (приемник):

// clock
input clk, - опорный тактовый сигнал
// reset
input reset, - синхронный сброс
// RXD
input RXD, - вход приемника
// control
input [15:0] UBRR, - делитель скорости UART (нужно записывать число на 1 меньше требуемого значения)
input [3:0] UBW, - количество семплов на один бит (нужно записывать число на 1 меньше требуемого значения)
input [3:0] num_bit, - количество бит (нужно записывать число на 1 меньше требуемого значения)
input MPCM, - режим детектирования адреса по 9-му биту
// data
input RD, - строб подтверждения чтения
output reg [7:0] RXB, - данные
output reg RXB8, - данные, 9 бит
// flag
output reg RXC, - флаг окончания приема
output reg FE, - флаг ошибки фрейма
output reg DOR - флаг переполнения буфера

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

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

Не забудте, что для того чтобы приемник нормально синхронизировался, оверсемплинг должен быть как минимум 4x, а лучше 8x.

Затем уже можете пробовать на реальном железе.

 

uart.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

08.05.2022 в 16:39, krux сказал:

со скоростью 115200

1) без ...

У автора задача с подтекстом, 16 МГц, поэтому:

0) без генератора на аккумуляторе фазы;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да я вообще не понял, о чём речь, когда тут более чем 150-кратный оаерсэмплинг. Фиксированные отметки времени гораздо проще оптимизировать в ресурсах, чем рассчитанные по формуле. Поэтому решение Тарасова более интересно, этим можно козырнуть при защите проекта :dirol:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Plain said:

У автора задача с подтекстом, 16 МГц, поэтому:

0) без генератора на аккумуляторе фазы;

Совсем не обязательно аккумулятор фазы.

16000000 Гц / 6 семплов на бит / 115200 = 23.14814815

Округляем до 23 и считаем ошибку.

16000000 Гц / 6 семплов на бит / 23 = 115942

(115942 / 115200 - 1) * 100 = 0.64409722%

Ошибка меньше 1% - будет работать без проблем.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообщем много что перечитал, попробовал сделать, вроде что-то получилось, но не знаю так ли это должно работать))? Делал со скоростью 57600

module RS232Receive(
    input clk,
    input rx,
    output reg [5:0] data, //liniya dannix
    output reg dataReady, //liniya gotovnosti
    output reg error  //signal oshibki
);

parameter Idle = 2'b00; //ojidanie
parameter StartBit = 2'b01; //startbit
parameter DataBit = 2'b10; // bit dannix
parameter StopBit = 2'b11; //stopbit
parameter Divider = 16'd278; //delitel schetchika

reg [3:0] state, nextState;  //registri sostoyaniya 1 tekyshee i 2 sledyeshee
reg [3:0] bitCount; //schetchik bit
reg [8:0] tickCount; //schetchik impylsov kvarcovogo generatora
reg [5:0] rData; //reg sbora prinyatogo bayta

initial begin

//NASHALNOE SOSTOYANIE REGISTROV

state = Idle;
nextState = Idle;
rData = 0;
bitCount = 4'b0000;
tickCount = 0;
error = 1'b0;
end

always @(posedge clk) //po perednemy fronty taktovogo signala prisvaivaem tekyshemy sostoyaniya
begin
state = nextState;
case(state)

//sostoyanie ojidaniya

Idle:
begin
rData = 8'h00; //sostoyanie ojidanie sbrasivaem registr prinyatogo bayta
tickCount = 0;
bitCount = 4'b0000;
error = 1'b0;
if (rx == 1'b0)
begin
nextState = StartBit;
end //esli na vhode 0, to sledyysheem sostoyaniem bydet startbit
end
      
StartBit:
begin

//shitaem impylsi, esli ih polovina ot vsei dlitelnosti bita to proveryaem sostoyanie linii dannix

tickCount = tickCount + 1; 
if (tickCount[8:0] == Divider[15:1])
begin
if (rx == 1'b0) //esli 0 to oshibki net
begin
error = 1'b0;
end else
begin
error = 1'b1; //esli 1 to oshibka i perehodim s sostoyanie ojidaniya
nextState = Idle;
end
end 
else
if (tickCount == Divider) //esli doshitali do konca bita, to sbrasivaem chetchiki i perehodim v sostoyanie priema
begin
tickCount = 0;
nextState = DataBit;
end
end

DataBit:
begin
tickCount = tickCount + 1;
if (tickCount[8:0] == Divider[15:1]) //takje schitaem do chentra bita
begin
rData[bitCount] = rx; // v registr ykladivaem kajdii schitaniy bit
bitCount = bitCount + 1;  //shitaem biti
end 

else
if (tickCount==Divider)  // kak doshli do konca bita
begin
tickCount = 0; //sbrasivaem schetchik esli prishlo eshe ne 6 bit to ostaemsya tyt je
if (bitCount == 6)
begin
bitCount = 0;
nextState = StopBit;
end

//esli prishlo 6, to perehodim k priemy stop bit
else

nextState = DataBit;
end
end

StopBit:
begin
tickCount = tickCount + 1;
if (tickCount[8:0] == Divider[15:1]) 
begin
if (rx == 1'b1) //proverka sostoyaniya vhodnoi linii, esli 1 to vse OK, esli 0 to oshibka
begin
error = 1'b0;
data = rData; //vistavlyaem na vihod registr prinyatogo bayta
dataReady = 1'b1; //signal gotov
end

else

begin
error = 1'b1; //oshibka
dataReady = 1'b0;
nextState = Idle; //perehodim v ojidanie
end
end else
if (tickCount == Divider)
begin
dataReady = 1'b0;
tickCount = 0;
nextState = Idle;
end
end
default: state = Idle;
endcase
end
endmodule

////////////////////////////////////////////

module RS232Receive_tb;

reg clk;
wire [5:0] data;
wire dataReady;
wire error;
reg rx;
RS232Receive r(
    .clk(clk),
    .data(data),
    .dataReady(dataReady),
    .error(error),
    .rx(rx)
);

always #5 clk = ~clk;
initial begin
    clk = 0; #5;
    rx = 1; #520800;
    rx = 0; #52080; //start
    rx = 0; #52080;
    rx = 1; #364560;
    rx = 1; #260400;

end
endmodule

123.PNG

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...