OpenCores
URL https://opencores.org/ocsvn/uart_observer/uart_observer/trunk

Subversion Repositories uart_observer

[/] [uart_observer/] [trunk/] [verilog/] [uart_observer.v] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 audriusa
`timescale 1ns / 1ps
2
 
3
//////////////////////////////////////////////////////////////////////////////////
4
// Company: none 
5
// Engineer: Audrius Meskauskas
6
// 
7
// Create Date: 03/10/2018 09:31:52 PM
8
// Design Name:  UART observer
9
// Module Name: uart_observer
10
// 
11
//////////////////////////////////////////////////////////////////////////////////
12
 
13
module uart_observer (
14
// clock, tested with 90 MHZ clock
15 3 audriusa
  input CLK_I,
16 2 audriusa
 
17
  // The array of observables.
18 3 audriusa
  input wire [BITS-1:0] DAT_I,
19 2 audriusa
 
20
  // UART  
21
  input CTS, // "clear to send"
22
 
23
  output TXD, // Serial data output
24
  output RTS  // Request to send, this UART does not send all the time.
25
);
26
 
27
 // The number of bits to show in the output
28
 parameter  BITS = 128;
29
 
30
// Clock frequency Hz
31
 parameter CLOCK_FREQ = 90_000_000;
32
 
33
 // Serial port speed baud
34
 parameter BAUDS = 921600; // 9600;
35
 
36
 parameter DIV_MAX = CLOCK_FREQ/BAUDS;
37
 
38
 parameter DIV_BITS = 32; // bits in frequency divider
39
 
40
 parameter N = 10;
41
 parameter H = N-1; // Highest bit
42
 
43
 // RAM buffer to transfer from 
44
 parameter RAM_LENGTH = 3 + 3 + 11*BITS;
45
 reg [7:0] mem [RAM_LENGTH - 1:0];
46
 // RAM index of value currently being sent
47
 reg [7:0] ram_addr = 0;
48
 
49
 // Divider to 1 baud                          
50
 reg [DIV_BITS:0] divider = 0;
51
 
52
 // Internal phase counter to track what we are doing
53
 reg [4:0] phase = 0;
54
 
55
 // The output data connector
56
 wire s_out;
57
 // The output "sending" connector
58
 reg sending = 0;
59
 
60
 // Main sending register
61
 reg [H:0] r_reg;
62
 
63
 wire [H:0] r_next;
64
 wire [H:0] r_sendit;
65
 
66
 // The byte being written
67
 reg [7:0] out; // = 8'b0011_0001;
68
 
69
 // New data from the buffer (start bit on the right)
70
 assign r_sendit = { 1'b1, out, 1'b0 };
71
 
72
 // Shifted value
73
 assign r_next = { 1'b0, r_reg [H:1] };
74
 // Out output (lowest bit)
75
 assign s_out = r_reg[0];
76
 
77
 reg [BITS-1:0] observables_reg;
78
 reg [BITS-1:0] observables_prev = 32'hFFFFF;
79
 
80
 parameter [7:0] ESC = 8'b0001_1011;
81
 
82
 integer b;
83
 integer p;
84
 integer bytes_in_row;
85
 
86
 // Initialize RAM with content to send
87
 initial
88
   begin
89
     // See http://www.termsys.demon.co.uk/vtansi.htm
90
     // Top left corner (ESC [ H)
91
 
92
     mem[0] <= ESC; // ESC
93
     mem[1] <= "["; // [
94
     mem[2] <= "H"; // H
95
 
96
     /*
97
     for (b = 3; b <= 3 + BITS*11; b = b + 11)
98
       render_byte(b);
99
     */
100
     bytes_in_row = 0;
101
     p = 3;
102
     for (b = 0; b < BITS/8; b = b + 1)
103
       begin
104
         if (bytes_in_row == 3)
105
           begin
106
             render_byte(p, 8'h0d, 8'h0a);
107
             bytes_in_row = 0;
108
           end
109
         else
110
           begin
111
             render_byte(p, " ", " ");
112
             bytes_in_row = bytes_in_row + 1;
113
           end;
114
         p = p + 11;
115
       end
116
 
117
     // Erase till end of screen (ESC [ J)
118
     mem[p] <= ESC; // ESC
119
     mem[p + 1] <= "["; // [
120
     mem[p + 2] <= "J"; // J    
121
   end
122
 
123
// Prepare initial data to render the byte (11 bytes - tetrad spacer and doubled byte spacer)
124
// The last two bytes (parameters) are inter-byte spacer that may be row separator.
125
task render_byte;
126
   input integer p;
127
   input reg [7:0] b1;
128
   input reg [7:0] b2;
129
 
130
   begin
131
     // (first tetrad 0 .. 3)
132
     mem[p + 4] <= " "; // Space separator
133
     // (second tetrad 5 .. 8)       
134
     // (Two spaces)    
135
     mem[p + 9] <= b1; // space
136
     mem[p + 10] <= b2; // space
137
   end
138
endtask
139
 
140
 // Convert a bit to ASCII representation of it.  
141
 function [7:0] ascii;
142
    input x;
143
    begin
144
      if (x==0)
145
        ascii = "."; // dot
146
      else
147
        ascii = "1";
148
    end
149
 endfunction
150
 
151
 // Loop over all 32 bits, populating memory cells with translated values.  
152
 task update_ram;
153
   integer k;
154
   integer b;
155
   integer ib; // bit
156
   integer p; // memory pointer
157
   begin
158
     ib = 0;
159
     p = 3; // Leave place for the header
160
     for (b = 0; b < BITS / 8; b = b + 1)
161
       begin
162
         for (k = 0; k < 4; k = k + 1)
163
           begin
164
             mem[p] = ascii(observables_reg[ib]);
165
             ib = ib + 1;
166
             p = p + 1;
167
           end
168
 
169
         p = p + 1; // spacer between tetrads
170
 
171
         for (k = 4; k < 8; k = k + 1)
172
           begin
173
             mem[p] = ascii(observables_reg[ib]);
174
             ib = ib + 1;
175
             p = p + 1;
176
           end
177
 
178
         p = p + 2; // spacer between bytes  
179
       end
180
   end
181
 endtask
182
 
183
 // Populate the register 'out' with next data to write  
184
 task next_data;
185
   begin
186
     out = mem[ram_addr];
187
     ram_addr = ram_addr + 1;
188
     if (ram_addr == RAM_LENGTH)
189
       ram_addr = 0;
190
   end
191
 endtask
192
 
193
 // Increement the "phase" variable that loops over 0-1-2-3-4-5-6-7-8-9-0
194
 task increment_phase;
195
   begin
196
     if (phase == 9)
197
       begin
198
         phase <= 0;
199
         observables_prev <= observables_reg;
200
       end
201
     else
202
       phase <= phase + 1;
203
   end
204
 endtask
205
 
206 3 audriusa
 always @(posedge CLK_I)
207 2 audriusa
 begin :cl
208
   // Need 781.25 (90000000 Hz to 115200 Hz)
209
   if (divider > DIV_MAX)
210
     begin
211
       if (phase == 0 && ram_addr == 0)
212
         begin
213 3 audriusa
           observables_reg = DAT_I;
214 2 audriusa
           if (observables_prev == observables_reg)
215
             begin
216
               r_reg <= 10'b1_1111_1111_1;
217
               divider <= 0;
218
               sending <= 0;
219
               disable cl;
220
             end
221
           else
222
             update_ram();
223
         end
224
 
225
       sending = 1;
226
       if (CTS == 0)
227
         begin
228
           // Not clear to send, keep inactive line high
229
           r_reg <= 10'b1_1111_1111_1;
230
           phase <= 0;
231
           divider <= 0;
232
           disable cl;
233
         end;
234
 
235
       if (phase == 0)
236
         begin
237
            next_data();
238
            r_reg = r_sendit;
239
         end
240
       else
241
         begin
242
           r_reg <= r_next;
243
         end;
244
 
245
       increment_phase();
246
 
247
       divider = 0;
248
     end
249
 
250
     divider = divider + 1;
251
 end
252
 
253
 assign TXD = s_out;
254
 assign RTS = sending;
255
 
256
endmodule
257
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.