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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [peripherals/] [UART_Rx.v] - Blame information for rev 6

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

Line No. Rev Author Line
1 2 sinclairrf
//
2
// PERIPHERAL UART_Rx:  @NAME@
3
//
4
// Technique:
5
// - optionally synchronize the incoming signal
6
// - optionally deglitch the incoming signal
7
// - identify edges, align with value before the edge
8
// - generate missing edges, align values
9
// - assemble received bit sequence
10
// - run state machine counting number of received bits and waiting for delayed start bits
11
// - validate bit sequence and output bit sequence at end of last stop bit
12
// - optional FIFO
13
//
14
localparam L__BAUDMETHOD = ((@BAUDMETHOD@)+1)/2;
15
localparam L__BAUDMETHOD_MINUS = L__BAUDMETHOD - 2;
16
localparam L__BAUDMETHOD_NBITS = $clog2(L__BAUDMETHOD+1);
17
localparam L__SYNC_LENGTH = @SYNC@;
18
localparam L__DEGLITCH_LENGTH = @DEGLITCH@;
19
localparam L__NSTOP = @NSTOP@;
20
localparam L__NRX = 1+8+L__NSTOP;
21
localparam L__EVENT_COUNT = 2*L__NRX-1;
22
localparam L__EVENT_COUNT_NBITS = $clog2(L__EVENT_COUNT+1);
23
localparam L__INFIFO = @INFIFO@;
24
localparam L__INFIFO_NBITS = $clog2((L__INFIFO==0)?1:L__INFIFO);
25
generate
26
// Either copy the input, register it, or put it through a synchronizer.
27
wire s__Rx_sync;
28
if (L__SYNC_LENGTH == 0) begin : gen__no_sync
29
  assign s__Rx_sync = @INPORT@;
30
end else if (L__SYNC_LENGTH == 1) begin : gen__short_sync
31
  reg s__Rx_inport_s = 1'b1;
32
  always @ (posedge i_clk)
33
    if (i_rst)
34
      s__Rx_inport_s <= 1'b1;
35
    else
36
      s__Rx_inport_s <= @INPORT@;
37
  assign s__Rx_sync = s__Rx_inport_s;
38
end else begin : gen__long_sync
39
  reg [L__SYNC_LENGTH-1:0] s__Rx_inport_s = {(L__SYNC_LENGTH){1'b1}};
40
  always @ (posedge i_clk)
41
    if (i_rst)
42
      s__Rx_inport_s <= {(L__SYNC_LENGTH){1'b1}};
43
    else
44
      s__Rx_inport_s <= { s__Rx_inport_s[0+:L__SYNC_LENGTH-1], @INPORT@ };
45
  assign s__Rx_sync = s__Rx_inport_s[L__SYNC_LENGTH-1];
46
end
47
// Either pass the received signal with no deglitching or apply deglitch
48
// hysteresis that consists of not changing the reported state unless all of
49
// the queued bits have changed state.
50
reg s__Rx_deglitched;
51
if (L__DEGLITCH_LENGTH == 0) begin : gen__nodeglitch
52
  always @ (*)
53
    s__Rx_deglitched = s__Rx_sync;
54
end else begin : gen__deglitch
55
  initial s__Rx_deglitched = 1'b1;
56
  reg [L__DEGLITCH_LENGTH-1:0] s__Rx_deglitch = {(L__DEGLITCH_LENGTH){1'b1}};
57
  always @ (posedge i_clk) begin
58
    s__Rx_deglitched <= (&(s__Rx_deglitch != {(L__DEGLITCH_LENGTH){s__Rx_deglitched}})) ? ~s__Rx_deglitched : s__Rx_deglitched;
59
    s__Rx_deglitch <= { s__Rx_deglitch[0+:L__DEGLITCH_LENGTH-1], @INPORT@ };
60
  end
61
end
62
// Identify edges
63
reg s__Rx_last = 1'b1;
64
always @ (posedge i_clk)
65
  if (i_rst)
66
    s__Rx_last <= 1'b1;
67
  else
68
    s__Rx_last <= s__Rx_deglitched;
69
reg s__Rx_edge = 1'b0;
70
always @ (posedge i_clk)
71
  if (i_rst)
72
    s__Rx_edge <= 1'b0;
73
  else
74
    s__Rx_edge <= (s__Rx_deglitched != s__Rx_last);
75
// Run a timer at twice the desired edge frequency rate.  Synchronize it to the
76
// incoming edges.
77
reg [L__BAUDMETHOD_NBITS-1:0] s__Rx_event_time = L__BAUDMETHOD_MINUS[L__BAUDMETHOD_NBITS-1:0];
78
reg s__Rx_event_time_msb = L__BAUDMETHOD_MINUS[L__BAUDMETHOD_NBITS-1];
79
wire s__Rx_event_time_expired = ({s__Rx_event_time_msb,s__Rx_event_time[L__BAUDMETHOD_NBITS-1]} == 2'b01);
80
always @ (posedge i_clk)
81
  if (i_rst) begin
82
    s__Rx_event_time <= L__BAUDMETHOD_MINUS[L__BAUDMETHOD_NBITS-1:0];
83
    s__Rx_event_time_msb <= L__BAUDMETHOD_MINUS[L__BAUDMETHOD_NBITS-1];
84
  end else if (s__Rx_edge || s__Rx_event_time_expired) begin
85
    s__Rx_event_time <= L__BAUDMETHOD_MINUS[L__BAUDMETHOD_NBITS-1:0];
86
    s__Rx_event_time_msb <= L__BAUDMETHOD_MINUS[L__BAUDMETHOD_NBITS-1];
87
  end else begin
88
    s__Rx_event_time <= s__Rx_event_time - { {(L__BAUDMETHOD_NBITS-1){1'b0}}, 1'b1 };
89
    s__Rx_event_time_msb <= s__Rx_event_time[L__BAUDMETHOD_NBITS-1];
90
  end
91
// Fabricate composite event detection.
92
reg s__Rx_idle;
93
wire s__Rx_wait_edge;
94
reg s__Rx_event = 1'b0;
95
always @ (posedge i_clk)
96
  if (i_rst)
97
    s__Rx_event <= 1'b0;
98
  else
99
    s__Rx_event <= ~s__Rx_event && ((s__Rx_wait_edge && s__Rx_edge) || (~s__Rx_idle && s__Rx_event_time_expired));
100
// State machine -- idle state and event (edge/fabricated-edge and midpoint) counter.
101
initial s__Rx_idle = 1'b1;
102
reg [L__EVENT_COUNT_NBITS-1:0] s__Rx_event_count = L__EVENT_COUNT[L__EVENT_COUNT_NBITS-1:0];
103
reg s__Rx_event_count_zero = 1'b1;
104
always @ (posedge i_clk)
105
  if (i_rst) begin
106
    s__Rx_event_count <= L__EVENT_COUNT[L__EVENT_COUNT_NBITS-1:0];
107
    s__Rx_idle <= 1'b1;
108
    s__Rx_event_count_zero <= 1'b1;
109
  end else begin
110
    if (s__Rx_idle && s__Rx_event)
111
      s__Rx_idle <= 1'b0;
112
    else
113
      s__Rx_idle <= (s__Rx_event_count_zero) ? 1'b1: s__Rx_idle;
114
    if (s__Rx_idle) begin
115
      s__Rx_event_count <= L__EVENT_COUNT[L__EVENT_COUNT_NBITS-1:0];
116
      s__Rx_event_count_zero <= 1'b0;
117
    end else if (s__Rx_event) begin
118
      s__Rx_event_count <= s__Rx_event_count - { {(L__EVENT_COUNT_NBITS-1){1'b0}}, 1'b1 };
119
      s__Rx_event_count_zero <= (s__Rx_event_count == { {(L__EVENT_COUNT_NBITS-1){1'b0}}, 1'b1 });
120
    end else begin
121
      s__Rx_event_count <= s__Rx_event_count;
122
      s__Rx_event_count_zero <= 1'b0;
123
    end
124
  end
125
assign s__Rx_wait_edge = s__Rx_idle || (L__EVENT_COUNT[0] ^ s__Rx_event_count[0]);
126
wire s__Rx_wait_sample = ~s__Rx_wait_edge;
127
// Generate a strobe when a new bit is to be recorded.
128
reg s__Rx_got_bit = 1'b0;
129
always @ (posedge i_clk)
130
  if (i_rst)
131
    s__Rx_got_bit <= 1'b0;
132
  else
133
    s__Rx_got_bit <= (~s__Rx_idle && s__Rx_wait_sample && s__Rx_event);
134
// Record the received bit stream after edges occur (start bit is always discarded)
135
reg [L__NRX-1:2] s__Rx_s = {(L__NRX-2){1'b1}};
136
always @ (posedge i_clk)
137
  if (i_rst)
138
    s__Rx_s <= {(L__NRX-2){1'b1}};
139
  else if (s__Rx_got_bit)
140
    s__Rx_s <= { s__Rx_last, s__Rx_s[3+:L__NRX-3] };
141
  else
142
    s__Rx_s <= s__Rx_s;
143
// Generate strobe to write the received byte to the output buffer.
144
reg s__Rx_wr = 1'b0;
145
reg [3:0] s__Rx_count = L__NRX[0+:4] - 4'd1;
146
always @ (posedge i_clk)
147
  if (i_rst) begin
148
    s__Rx_wr <= 1'b0;
149
    s__Rx_count <= L__NRX[0+:4] - 4'd1;
150
  end else if (s__Rx_idle) begin
151
    s__Rx_wr <= 1'b0;
152
    s__Rx_count <= L__NRX[0+:4] - 4'd1;
153
  end else if (s__Rx_got_bit) begin
154
    s__Rx_wr <= (s__Rx_count == 4'd1);
155
    s__Rx_count <= s__Rx_count - 4'd1;
156
  end else begin
157
    s__Rx_wr <= 1'b0;
158
    s__Rx_count <= s__Rx_count;
159
  end
160
// Optional FIFO
161 6 sinclairrf
@RTR_BEGIN@
162
reg s__rtr = 1'b1;
163
@RTR_END@
164 2 sinclairrf
if (L__INFIFO == 0) begin : gen__nofifo
165
  always @ (posedge i_clk)
166
    if (i_rst) begin
167
      s__Rx_empty <= 1'b1;
168
      s__Rx <= 8'h00;
169
    end else begin
170
      if (s__Rx_wr)
171
        s__Rx <= s__Rx_s[2+:8];
172
      else
173
        s__Rx <= s__Rx;
174
      if (s__Rx_wr) begin
175
        if (s__Rx_rd)
176
          s__Rx_empty <= s__Rx_empty;
177
        else
178
          s__Rx_empty <= 1'b0;
179
      end else begin
180
        if (s__Rx_rd)
181
          s__Rx_empty <= 1'b1;
182
        else
183
          s__Rx_empty <= s__Rx_empty;
184
      end
185
    end
186 6 sinclairrf
  @RTR_BEGIN@
187
  always @ (posedge i_clk)
188
    if (i_rst)
189
      s__rtr <= 1'b1;
190
    else
191
      s__rtr <= ~s__Rx_idle;
192
  @RTR_END@
193 2 sinclairrf
end else begin : gen__fifo
194
  reg [L__INFIFO_NBITS:0] s__Rx_fifo_addr_in;
195
  reg [L__INFIFO_NBITS:0] s__Rx_fifo_addr_out;
196
  wire s__Rx_shift;
197
  reg s__Rx_fifo_has_data = 1'b0;
198
  always @ (posedge i_clk)
199
    if (i_rst)
200
      s__Rx_fifo_has_data <= 1'b0;
201
    else
202
      s__Rx_fifo_has_data <= (s__Rx_fifo_addr_out != s__Rx_fifo_addr_in) && !s__Rx_shift;
203
  always @ (posedge i_clk)
204
    if (i_rst) begin
205
      s__Rx_empty <= 1'b1;
206
    end else begin
207
      case ({ s__Rx_fifo_has_data, s__Rx_empty, s__Rx_rd })
208
        3'b000 :  s__Rx_empty <= 1'b0;
209
        3'b001 :  s__Rx_empty <= 1'b1; // good read
210
        3'b010 :  s__Rx_empty <= 1'b1;
211
        3'b011 :  s__Rx_empty <= 1'b1; // bad read
212
        3'b100 :  s__Rx_empty <= 1'b0;
213
        3'b101 :  s__Rx_empty <= 1'b0; // shift, good read
214
        3'b110 :  s__Rx_empty <= 1'b0; // shift
215
        3'b111 :  s__Rx_empty <= 1'b1; // shift, bad read
216
      endcase
217
    end
218
  assign s__Rx_shift = s__Rx_fifo_has_data && (s__Rx_empty || s__Rx_rd);
219
  reg s__Rx_full = 1'b0;
220
  always @ (posedge i_clk)
221
    if (i_rst)
222
      s__Rx_full <= 1'b0;
223
    else
224
      s__Rx_full <= (s__Rx_fifo_addr_in == (s__Rx_fifo_addr_out ^ { 1'b1, {(L__INFIFO_NBITS){1'b0}} }));
225
  reg [7:0] s__Rx_fifo_mem[@INFIFO@-1:0];
226
  initial s__Rx_fifo_addr_in = {(L__INFIFO_NBITS+1){1'b0}};
227
  always @ (posedge i_clk)
228
    if (i_rst)
229
      s__Rx_fifo_addr_in <= {(L__INFIFO_NBITS+1){1'b0}};
230
    else if (s__Rx_wr && (!s__Rx_full || s__Rx_shift)) begin
231
      s__Rx_fifo_addr_in <= s__Rx_fifo_addr_in + { {(L__INFIFO_NBITS){1'b0}}, 1'b1 };
232
      s__Rx_fifo_mem[s__Rx_fifo_addr_in[0+:L__INFIFO_NBITS]] <= s__Rx_s[2+:8];
233
    end else
234
      s__Rx_fifo_addr_in <= s__Rx_fifo_addr_in;
235
  initial s__Rx_fifo_addr_out = {(L__INFIFO_NBITS+1){1'b0}};
236
  always @ (posedge i_clk)
237
    if (i_rst) begin
238
      s__Rx_fifo_addr_out <= {(L__INFIFO_NBITS+1){1'b0}};
239
      s__Rx <= 8'h00;
240
    end else if (s__Rx_shift) begin
241
      s__Rx_fifo_addr_out <= s__Rx_fifo_addr_out + { {(L__INFIFO_NBITS){1'b0}}, 1'b1 };
242
      s__Rx <= s__Rx_fifo_mem[s__Rx_fifo_addr_out[0+:L__INFIFO_NBITS]];
243
    end else begin
244
      s__Rx_fifo_addr_out <= s__Rx_fifo_addr_out;
245
      s__Rx <= s__Rx;
246
    end
247 6 sinclairrf
  @RTR_BEGIN@
248
  // Isn't ready to receive if the FIFO is full or if the FIFO is almost full
249
  // and there is incoming data (i.e., receiver is not idle).
250
  reg s__Rx_idle_s = 1'b0;
251
  always @ (posedge i_clk)
252
    if (i_rst)
253
      s__Rx_idle_s <= 1'b0;
254
    else
255
      s__Rx_idle_s <= s__Rx_idle;
256
  reg s__Rx_wr_s = 1'b0;
257
  always @ (posedge i_clk)
258
    if (i_rst)
259
      s__Rx_wr_s <= 1'b0;
260
    else
261
      s__Rx_wr_s <= s__Rx_wr;
262
  reg s__Rx_busy = 1'b0;
263
  always @ (posedge i_clk)
264
    if (i_rst)
265
      s__Rx_busy <= 1'b0;
266
    else if ({s__Rx_idle_s, s__Rx_idle} == 2'b10)
267
      s__Rx_busy <= 1'b1;
268
    else if (s__Rx_wr_s)
269
      s__Rx_busy <= 1'b0;
270
    else
271
      s__Rx_busy <= s__Rx_busy;
272
  reg s__Rx_almost_full = 1'b0;
273
  always @ (posedge i_clk)
274
    if (i_rst)
275
      s__Rx_almost_full <= 1'b0;
276
    else
277
      s__Rx_almost_full <= (s__Rx_fifo_addr_in == (s__Rx_fifo_addr_out + { 1'b0, {(L__INFIFO_NBITS){1'b1}} }));
278
  always @ (posedge i_clk)
279
    if (i_rst)
280
      s__rtr <= 1'b1;
281
    else
282
//      s__rtr <= ~(s__Rx_full  || (s__Rx_almost_full && ~s__Rx_idle));
283
      s__rtr <= ~(s__Rx_full  || (s__Rx_almost_full && s__Rx_busy));
284
  @RTR_END@
285 2 sinclairrf
end
286 6 sinclairrf
@RTR_BEGIN@
287
always @ (*)
288
  @RTR_SIGNAL@ <= @RTR_INVERT@s__rtr;
289
@RTR_END@
290 2 sinclairrf
endgenerate

powered by: WebSVN 2.1.0

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