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

Subversion Repositories ssbcc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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