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

Subversion Repositories socgen

[/] [socgen/] [trunk/] [common/] [opencores.org/] [Testbench/] [bfms/] [uart_model/] [rtl/] [verilog/] [serial_xmit] - Blame information for rev 131

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 131 jt_eaton
/**********************************************************************/
2
/*                                                                    */
3
/*             -------                                                */
4
/*            /   SOC  \                                              */
5
/*           /    GEN   \                                             */
6
/*          /     LIB    \                                            */
7
/*          ==============                                            */
8
/*          |            |                                            */
9
/*          |____________|                                            */
10
/*                                                                    */
11
/*  Generic model for a serial asynchronous transmitter               */
12
/*                                                                    */
13
/*  Author(s):                                                        */
14
/*      - John Eaton, jt_eaton@opencores.org                          */
15
/*                                                                    */
16
/**********************************************************************/
17
/*                                                                    */
18
/*    Copyright (C) <2010>                     */
19
/*                                                                    */
20
/*  This source file may be used and distributed without              */
21
/*  restriction provided that this copyright statement is not         */
22
/*  removed from the file and that any derivative work contains       */
23
/*  the original copyright notice and the associated disclaimer.      */
24
/*                                                                    */
25
/*  This source file is free software; you can redistribute it        */
26
/*  and/or modify it under the terms of the GNU Lesser General        */
27
/*  Public License as published by the Free Software Foundation;      */
28
/*  either version 2.1 of the License, or (at your option) any        */
29
/*  later version.                                                    */
30
/*                                                                    */
31
/*  This source is distributed in the hope that it will be            */
32
/*  useful, but WITHOUT ANY WARRANTY; without even the implied        */
33
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR           */
34
/*  PURPOSE.  See the GNU Lesser General Public License for more      */
35
/*  details.                                                          */
36
/*                                                                    */
37
/*  You should have received a copy of the GNU Lesser General         */
38
/*  Public License along with this source; if not, download it        */
39
/*  from http://www.opencores.org/lgpl.shtml                          */
40
/*                                                                    */
41
/**********************************************************************/
42
 
43
module
44
uart_model_serial_xmit
45
#(parameter   WIDTH=8,   // Number of data bits
46
  parameter   SIZE=4     // binary size of shift_cnt, must be able to hold  WIDTH + 4 states
47
 )
48
 
49
 
50
(
51
input  wire              clk,
52
input  wire              reset,
53
input  wire              edge_enable,                 // one pulse per bit time for data rate timing
54
input  wire              parity_enable,               // 0 = no parity bit sent, 1= parity bit sent
55
input  wire              two_stop_enable,             // 0 = 1 stop bit, 1 = 2 stop bits
56
input  wire  [1:0]       parity_type,                 // 00= odd,01=even,10=force a 0,11= force a 1
57
input  wire              load,                        // start transmiting data
58
input  wire              start_value,                 // value out at start bit time
59
input  wire              stop_value,                  // value out for stop bit also used for break
60
input  wire [WIDTH-1:0]  data,                        // data byte
61
 
62
output  reg              buffer_empty,                // ready for next byte
63
output  reg              ser_out                      // to pad_ring
64
                         );
65
 
66
reg [SIZE-1:0]           shift_cnt;
67
reg [WIDTH-1:0]          shift_buffer;
68
reg                      parity_calc;
69
reg                      delayed_edge_enable;
70
 
71
 
72
//
73
//   shift_cnt controls the serial bit out
74
//
75
//   0           Start bit
76
//   1-> WIDTH   Data bit lsb first
77
//   WIDTH+1     Parity bit if enabled
78
//   2^SIZE-2    Second stop bit if enabled
79
//   2^SIZE-1    Last stop bit and idle
80
 
81
always@(posedge clk)
82
  if(reset || buffer_empty)                                        shift_cnt   <= {SIZE{1'b1}};
83
  else
84
  if(!edge_enable)                                                 shift_cnt   <= shift_cnt;
85
  else
86
  if(( shift_cnt ==  {SIZE{1'b1}}  ) &&  ! buffer_empty )          shift_cnt   <= {SIZE{1'b0}};
87
  else
88
  if ( shift_cnt == WIDTH)
89
    case({two_stop_enable,parity_enable})
90
      (2'b00):                                                     shift_cnt   <= {SIZE{1'b1}};
91
      (2'b01):                                                     shift_cnt   <= shift_cnt + 1'b1;
92
      (2'b10):                                                     shift_cnt   <= {SIZE{1'b1}} - 1'b1;
93
      (2'b11):                                                     shift_cnt   <= shift_cnt + 1'b1;
94
    endcase // case ({two_stop_enable,parity_enable})
95
  else
96
  if ( shift_cnt == (WIDTH+1))
97
    case( two_stop_enable)
98
      (1'b0):                                                      shift_cnt   <= {SIZE{1'b1}};
99
      (1'b1):                                                      shift_cnt   <= {SIZE{1'b1}} - 1'b1;
100
    endcase
101
  else                                                             shift_cnt   <= shift_cnt + 1'b1;
102
 
103
//
104
//
105
//   Clear buffer_empty upon load pulse
106
//   set it back at the start of the final stop pulse
107
//   if load happens BEFORE the next edge_enable then data transfer will have no pauses
108
//   logic ensures that having load happen on a edge_enable will work
109
//
110
 
111
always@(posedge clk)
112
   if(reset)                                                       delayed_edge_enable <= 1'b0;
113
   else                                                            delayed_edge_enable <= edge_enable && ! load;
114
 
115
 
116
always@(posedge clk)
117
if(reset)                                                          buffer_empty <= 1'b1;
118
else
119
if(load)                                                           buffer_empty <= 1'b0;
120
else
121
if((shift_cnt == {SIZE{1'b1}}) && delayed_edge_enable)
122
                                                                   buffer_empty <= 1'b1;
123
else                                                               buffer_empty <= buffer_empty;
124
 
125
 
126
 
127
 
128
 
129
//
130
//
131
//   load shift_buffer during start_bit
132
//   shift down every bit
133
//
134
//
135
always@(posedge clk)
136
  if(reset)                                                        shift_buffer <= {WIDTH{1'b0}};
137
  else
138
  if(!edge_enable)                                                 shift_buffer <= shift_buffer;
139
  else
140
  if(shift_cnt == {SIZE{1'b0}})                                    shift_buffer <= data;
141
  else                                                             shift_buffer <= {1'b0,shift_buffer[WIDTH-1:1]};
142
 
143
 
144
 
145
 
146
 
147
 
148
//
149
//
150
//   calculate parity on the fly
151
//   seed reg with 0 for odd and 1 for even
152
//   force reg to 0 or 1 if needed
153
//
154
always@(posedge clk)
155
  if(reset)                                                        parity_calc <= 1'b0;
156
  else
157
  if(!edge_enable)                                                 parity_calc <= parity_calc;
158
  else
159
  if(parity_type[1] || (shift_cnt == {SIZE{1'b0}}))                parity_calc <= parity_type[0];
160
  else                                                             parity_calc <= parity_calc ^ shift_buffer[0];
161
 
162
 
163
//   send start_bit,data,parity and stop  based on shift_cnt
164
 
165
 
166
   always@(posedge clk)
167
     if(reset)                                                     ser_out <= stop_value;
168
     else
169
     if( shift_cnt == {SIZE{1'b0}} )                               ser_out <= start_value;
170
     else
171
     if( shift_cnt == {SIZE{1'b1}} )                               ser_out <= stop_value;
172
     else
173
     if( shift_cnt == ({SIZE{1'b1}}+1'b1) )                        ser_out <= stop_value;
174
     else
175
     if( shift_cnt == (WIDTH+1) )                                  ser_out <= parity_calc;
176
     else                                                          ser_out <= shift_buffer[0];
177
 
178
 
179
endmodule
180
 
181
 

powered by: WebSVN 2.1.0

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