-
Notifications
You must be signed in to change notification settings - Fork 1
/
RS232_Norbo.py
277 lines (239 loc) · 9.07 KB
/
RS232_Norbo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#!/usr/bin/env python
# Description: UART Receiver and Transmitter with Receive- and Transmitbuffer
#
# Module Signals:
# +++++++++++++++
#iClk -> Clock Signal
#iRst -> Reset Signal
#iRX -> Receiver input Signal
#oTX -> Transmitter output Signal
#iData -> Data to write to the transmit-buffer
#WriteEnable -> Strobe this signal to write iData to the transmit-buffer (write address is incremmented in the Module)
#oWrBuffer_full -> Indicates that the transmit-buffer is full. If Data is strobed when the transmit-buffer is indicated full it is ignored
#oData -> Output data at the read_addr of the receive-buffer. (oData<=receive-buffer[read_addr] on the next iClk clock-edge)
#read_addr -> Address to read from the receive-buffer
#oRx_addr -> Address where the next byte which will be received will be put into the receive-buffer
#Clkfrequenz -> Constant which should be set to the frequency of iClk
#Baudrate -> Constant to set the Baudrate of the unit.
#RX_BUFFER_LENGTH -> Constant, sets the receive-buffer size
#TX_BUFFER_LENGTH -> Constant, sets the transmit-buffer size
#
# Author: Norbert Feurle
# Last edit Date: 11.5.2012
# Licence: Only use it to do good, no garantie warranty
from myhdl import *
def RS232_Module(iClk,iRst,iRX,oTX, iData,WriteEnable,oWrBuffer_full,oData,read_addr,oRx_addr,Clkfrequenz=12e6,Baudrate=38400,RX_BUFFER_LENGTH=8,TX_BUFFER_LENGTH=8):
##### Constants #####
CounterCycle=int(Clkfrequenz/Baudrate)
CounterCycle_half=int(Clkfrequenz/(Baudrate*2.0))
##### Signal definitions for Receiver Part ####
Receive_RAM=[Signal(intbv(0)[8:]) for i in range(RX_BUFFER_LENGTH)]
rx_counter=Signal(intbv(0,min=0,max=CounterCycle+2))
rx_currentData=Signal(intbv(0)[9:])
rx_bit_count=Signal(intbv(0,min=0,max=10))
rx_addr=Signal(intbv(0,min=0,max=RX_BUFFER_LENGTH))
rx_State=Signal(intbv(0,min=0,max=4))
##### Signal definitions for Transmitter Part ####
Transmit_RAM=[Signal(intbv(0)[8:]) for i in range(TX_BUFFER_LENGTH)]
tx_counter=Signal(intbv(0,min=0,max=CounterCycle+2))
tx_bit_count=Signal(intbv(0,min=0,max=11))
tx_addr=Signal(intbv(0,min=0,max=TX_BUFFER_LENGTH))
write_addr=Signal(intbv(0,min=0,max=TX_BUFFER_LENGTH))
tx_State=Signal(intbv(0,min=0,max=4))
SendREG=Signal(intbv(0)[10:])
sig_WrBuffer_full=Signal(bool(0))
@always_comb
def comb2_logic():
oWrBuffer_full.next=sig_WrBuffer_full
@always_comb
def comb_logic():
if ((write_addr+1)%TX_BUFFER_LENGTH)==tx_addr:
sig_WrBuffer_full.next=True
else:
sig_WrBuffer_full.next=False
@always(iClk.posedge,iRst.negedge)
def seq_logic():
if iRst==0:
###### Resets Receiver Part #####
rx_State.next=0
rx_counter.next=0
rx_currentData.next=0
rx_bit_count.next=0
rx_addr.next=0
oRx_addr.next=0
###### Resets Transmitter Part #####
tx_State.next=0
tx_addr.next=0
write_addr.next=0
SendREG.next=0
tx_counter.next=0
tx_bit_count.next=0
else:
oRx_addr.next=rx_addr
oData.next=Receive_RAM[read_addr]
oTX.next=1
################## Receiver Part ################
if rx_State==0: #IDLE STATE
if iRX==0:
rx_counter.next=rx_counter+1
else:
rx_counter.next=0
if rx_counter==CounterCycle_half:
rx_State.next=1
rx_counter.next=0
rx_bit_count.next=0
elif rx_State==1: #RECEIVING STATE
rx_counter.next=rx_counter+1
if rx_counter==0:
rx_currentData.next=concat(iRX,rx_currentData[9:1])
rx_bit_count.next=rx_bit_count+1
if rx_counter==CounterCycle:
rx_counter.next=0
if rx_bit_count==9:
rx_State.next=2
rx_counter.next=0
elif rx_State==2: #STOPBIT STATE
rx_counter.next=rx_counter+1
if rx_counter==CounterCycle:
rx_State.next=0
rx_counter.next=0
if iRX==1: #Stopbit is Received
Receive_RAM[rx_addr].next=rx_currentData[9:1]
rx_addr.next=(rx_addr+1)%RX_BUFFER_LENGTH
################## Transmitter Part ################
#### Writing Data to Transmit Buffer ####
#TODO Buffer full flag#
if WriteEnable and (not sig_WrBuffer_full):
Transmit_RAM[write_addr].next=iData
write_addr.next=(write_addr+1)%TX_BUFFER_LENGTH
#### Transmitting Statmachine ####
if tx_State==0:
if write_addr!=tx_addr:
tx_counter.next=0
tx_State.next=1
tx_bit_count.next=0
SendREG.next=concat(intbv(1)[1:],Transmit_RAM[tx_addr],intbv(0)[1:])
tx_addr.next=(tx_addr+1)%TX_BUFFER_LENGTH
elif tx_State==1: ### Send Bytes
oTX.next=SendREG[tx_bit_count]
tx_counter.next=tx_counter+1
if tx_counter==CounterCycle:
tx_bit_count.next=tx_bit_count+1
tx_counter.next=0
if tx_bit_count==9:
tx_State.next=0
return seq_logic,comb_logic,comb2_logic
def test_bench():
###### Constnats #####
Clk_f=12e6 #12 Mhz
BAUDRATE=38400
##### Signal definitions #####
iData=Signal(intbv(0)[8:])
oData=Signal(intbv(0)[8:])
iClk=Signal(bool(0))
iRst=Signal(bool(1))
iRX=Signal(bool(1))
oTX=Signal(bool(0))
WriteEnable=Signal(bool(0))
oWrBuffer_full=Signal(bool(0))
read_addr=Signal(intbv(0,min=0,max=8))
RX_BUFF_LEN=8
rx_addr=Signal(intbv(0,min=0,max=RX_BUFF_LEN))
##### Instanziate RS232 Module #####
rs232_instance=RS232_Module(iClk,iRst,iRX,oTX, iData,WriteEnable, \
oWrBuffer_full,oData,read_addr,rx_addr,Clkfrequenz=Clk_f, \
Baudrate=BAUDRATE,RX_BUFFER_LENGTH=RX_BUFF_LEN)
##### Convert to VHDL ######
#toVHDL(RS232_Module,iClk,iRst,iRX,oTX, iData,WriteEnable, \
# oWrBuffer_full,oData,read_addr,rx_addr,Clkfrequenz=Clk_f, \
# Baudrate=BAUDRATE,RX_BUFFER_LENGTH=RX_BUFF_LEN)
interval = delay(10)
@always(interval)
def clk_gen():
iClk.next=not iClk
@always_comb
def rs232loopback():
iRX.next=oTX
def Write_to_rs232_send_buffer(value):
yield iClk.posedge
iData.next=value
if oWrBuffer_full:
print "Value:",value,"\tNot written, RS232 Transmittbuffer has indiciated to be allready full. (by oWrBuffer_full)"
WriteEnable.next=1
yield iClk.posedge
WriteEnable.next=0
def TestTransmitReceive(testARRAY):
#### Write some Bytes to the Sendbuffer #####
for data in testARRAY:
yield Write_to_rs232_send_buffer(data)
#### wait until data is received #####
count=0
currentArryPos=0
while 1:
yield iClk.posedge
yield delay(0)
count=count+1
if rx_addr!=read_addr:
count=0
print "RXData:", oData,"\tTXData:",testARRAY[currentArryPos], "\t\tBuffer Address:",read_addr
assert testARRAY[currentArryPos]==oData
currentArryPos=currentArryPos+1
read_addr.next=(read_addr+1)%RX_BUFF_LEN
#if Nothing is received for six possible complete RS232 transmissions
# (8+2) means 8 Bits + 1 Startbit + 1 Stopbit
if count>((Clk_f*1.0/BAUDRATE)*(8+2)*6):
if not (currentArryPos==len(testARRAY)):
print "Warning: Not all values of the Array have been received (Check if Transmittbuffer was full)"
print "Missing Data is:", testARRAY[currentArryPos:]
break
@instance
def stimulus():
#### Reseting #####
iRst.next=1
yield delay(50)
iRst.next=0
yield delay(50)
iRst.next=1
yield delay(50)
#### Some Test Data ####
testARRAY=[0x55,0xAA,0xff,0,1,128,0xef,0xfe]
print
print "Running Test Array:",testARRAY
print "#"*50
yield TestTransmitReceive(testARRAY)
#### Some Test Data ####
testARRAY=[8,4,5,2,1,0]
print
print "Running Test Array:",testARRAY
print "#"*50
yield TestTransmitReceive(testARRAY)
#### Some Test Data ####
testARRAY=[255,254,253,251]
print
print "Running Test Array:",testARRAY
print "#"*50
yield TestTransmitReceive(testARRAY)
#### Reseting #####
iRst.next=1
yield delay(50)
iRst.next=0
yield delay(50)
iRst.next=1
yield delay(50)
### artificial reset of read_addr ####
read_addr.next=0
#### Some Test Data ####
testARRAY=[0x55,0xAA,0xff,0,1,128,0xef,0xfe,8,89,55]
print
print "Running Test Array:",testARRAY
print "#"*50
yield TestTransmitReceive(testARRAY)
print
print "End of Simulation, simulation succesfull!"
raise StopSimulation
return clk_gen,rs232loopback,stimulus,rs232_instance#,Monitor_oTX
if __name__ == '__main__':
tb = traceSignals(test_bench)
sim= Simulation(tb)
#sim = Simulation(test_bench())
sim.run()