§ Верхний уровень

1serial SERIAL(
2
3    .clk12    (),      // Частота
4    .rx       (),      // Входящие данные
5    .rx_byte  (),      // Исходящий байт (8 bit)
6    .rx_ready ()       // Строб готовности
7);

§ Код модуля

  • Модуль приёмопередатчика UART (FTDI Marsohod)
  • Скорость: 460800 бод, эквивалентно 51200 байт в секунду (50 кб в секунду)
  • Длина: 1 старт бит + 8 бит (байт) + 1 (бит чётности)
1module serial(
2    input   wire            clk12,          // Частота 12,00 MHZ
3    input   wire            rx,             // Входящие данные
4    output  reg     [7:0]   rx_byte,        // Исходящий байт
5    output  wire            rx_ready        // Бит готовности
6);
7
8// 460800 baud
9parameter R_COUNT = 26;     // Полный период (12'000'000 / 26 ~ 460800 бод)
10
11reg [8:0] rc_data;          // Исходящие данные
12reg [1:0] latch;            // Детектор спада фронта
13reg [6:0] period   = 1'b0;  // Период между битами
14reg [3:0] num_bits = 1'b0;  // Количество считанных битов (0..8)
15reg [1:0] flg      = 1'b0;  // Логика, позволяющая установить строб готовности
16reg       waiting  = 1'b1;  // По умолчанию, режим приёма включён
17
18// Формируется строб готовности после 1 такта по приёму
19assign rx_ready = (flg == 2'b10);
20
21// С помощью двух подряд идущих битов определяем, когда будет спад, чтобы начать приём
22always @(posedge clk12) latch <= {latch[0], rx};
23
24// Признак окончания данных
25wire eof = (period == R_COUNT-1 && num_bits == 4'd9);
26
27// Распределение входящих битов данных
28// num_bits =     9      8 7 6 5 4 3 2 1    0    <--- справа налево
29//            Четность [     Данные     ] Старт
30
31// Основной модуль приёма
32always @(posedge clk12) begin
33
34    // Обнаружен спад во время ожидания данных - это стартовый бит.
35    // Переключаемся в режим приёма данных
36    if (waiting && latch[1:0] == 2'b10) begin
37        waiting <= 1'b0;
38
39    end
40
41    // Сейчас мы в режиме приема данных
42    else if (!waiting) begin
43
44        // Сброс периода, и просмотр результатов
45        if (period == R_COUNT-1) begin
46
47            period <= 1'b0;
48
49            // Был принят последний бит, в режим ожидания
50            if (num_bits == 4'd9) begin
51
52                waiting  <= 1'b1;           // В режим ожидания спада (старт-бита)
53                num_bits <= 1'b0;           // Для следующего раза
54                rx_byte  <= rc_data[7:0];   // Берем итоговые данные (без старт бита и бита чётности, 8-я позиция)
55
56            // К следующему биту
57            end else num_bits <= num_bits + 1'b1;
58
59        end
60        else begin
61
62            // Обнаружен полупериод - пишет данные
63            if (period == R_COUNT / 2) rc_data <= {latch[1], rc_data[8:1]};
64
65            // Считаем количество тиков
66            period <= period + 1'b1;
67
68        end
69
70    end
71
72    // Пишется бит EOF, на следующем такте будет выставлен 1 (строб), который потом исчезнет на ещё одном такте
73    flg <= {flg[0], eof};
74
75end
76
77endmodule