forked from udara28/SDRAM_Controller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sd_intf.py
123 lines (107 loc) · 5.23 KB
/
sd_intf.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
from myhdl import *
from math import log
class sd_intf(object):
addr_width = 13
data_width = 16
# constant for sdram
SDRAM_NROWS_C = 8192 # Number of rows in SDRAM array.
SDRAM_NCOLS_C = 512 # Number of columns in SDRAM array.
SDRAM_DATA_WIDTH_C = 16 # Host & SDRAM data width.
SDRAM_HADDR_WIDTH_C = 24 # Host-side address width.
SDRAM_SADDR_WIDTH_C = 13 # SDRAM-side address width.
SDRAM_T_INIT_C = 20000.0 #200000.0 # Min initialization interval (ns).
SDRAM_T_RAS_C = 45.0 # Min interval between active to precharge commands (ns).
SDRAM_T_RCD_C = 20.0 # Min interval between active and R/W commands (ns).
SDRAM_T_REF_C = 64000000.0 # Maximum refresh interval (ns).
SDRAM_T_RFC_C = 65.0 # Duration of refresh operation (ns).
SDRAM_T_RP_C = 20.0 # Min precharge command duration (ns).
SDRAM_T_XSR_C = 75.0 # Exit self-refresh time (ns).
SDRAM_FREQ_C = 100.0 # Operating frequency in MHz.
SDRAM_IN_PHASE_C = True # SDRAM and controller XESS on same or opposite clock edge.
SDRAM_PIPE_EN_C = False # If true, enable pipelined read operations.
SDRAM_ENABLE_REFRESH_C = True # If true, row refreshes are automatically inserted.
SDRAM_MULTIPLE_ACTIVE_ROWS_C = False # If true, allow an active row in each bank.
SDRAM_MAX_NOP_C = 10000 # Number of NOPs before entering self-refresh.
SDRAM_BEG_ADDR_C = 16 #00_0000#; -- Beginning SDRAM address.
SDRAM_END_ADDR_C = 16 #FF_FFFF#; -- Ending SDRAM address.
SDRAM_NOP_CMD_C = intbv("0111")[4:] #0,1,1,1,0,0
SDRAM_ACTIVE_CMD_C = intbv("0011")[4:] #0,0,1,1,0,0
SDRAM_READ_CMD_C = intbv("0101")[4:] # 0,1,0,1,0,0
SDRAM_WRITE_CMD_C = intbv("0100")[4:] # 0,1,0,0,0,0
SDRAM_PCHG_CMD_C = intbv("0010")[4:] # 0,0,1,0,0,0
SDRAM_MODE_CMD_C = intbv("0000")[4:] # 0,0,0,0,0,0
SDRAM_RFSH_CMD_C = intbv("0001")[4:] # 0,0,0,1,0,0
SDRAM_MODE_C = intbv("00_0_00_011_0_000")[12:] # mode command for set_mode command
SDRAM_ALL_BANKS_C = intbv("001000000000")[12:] # value of CMDBIT to select all banks
SDRAM_ONE_BANK_C = intbv("000000000000")[12:]
timing = { # timing details refer data sheet
'init' : 100, # min init interval
'ras' : 10, # min interval between active prechargs
'rcd' : 10, # min interval between active R/W
'cas' : 20,
'ref' : 64000000, # max refresh interval
'rfc' : 65, # refresh opertaion
'rp' : 20, # min precharge
'xsr' : 75, # exit self-refresh time
'wr' : 55, # @todo ...
}
def __init__(self):
self.cke = Signal(bool(0))
self.cs = Signal(bool(0))
self.cas = Signal(bool(0))
self.ras = Signal(bool(0))
self.we = Signal(bool(0))
self.bs = Signal(intbv(0)[2:])
self.addr = Signal(intbv(0)[self.addr_width:])
self.dqml = Signal(bool(0))
self.dqmh = Signal(bool(0))
self.dq = TristateSignal(intbv(0)[self.data_width:])
# Written below are transactors for passing commands to sdram
def nop(self,clk):
# [NOP] cs ras cas we : L H H H
self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,1,1,1
yield clk.posedge
def activate(self,clk,row_addr,bank_id=0):
self.bs.next = bank_id
self.addr.next = row_addr
# [ACTIVE] cs ras cas we : L L H H
self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,0,1,1
yield clk.posedge
def loadMode(self,clk,mode='burst',cas=3,burst=1):
addr = 0
if(mode.lower() == 'single'):
addr = addr + 2**9
addr = addr + cas*(2**4)
addr = addr + int(log(burst,2))
self.addr.next = addr
# [LOAD_MODE] cs ras cas we dqm : L L L L X
self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,0,0,0
yield clk.posedge
yield clk.posedge
def precharge(self,clk,bank_id=None):
if(bank_id == None): # precharge all banks
self.addr.next = 2**10 # A10 is high
else:
self.addr.next = 0
self.bs.next = bank_id
# [PRECHARGE] cs ras cas we : L L H L
self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,0,1,0
yield clk.posedge
def read(self,clk,addr,bank_id=0):
self.bs.next = bank_id
self.addr.next = addr
# [READ] # cs ras cas we dqm : L H L H X
self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,1,0,1
yield clk.posedge
yield clk.posedge
def write(self,clk,driver,addr,value,bank_id=0):
self.bs.next = bank_id
self.addr.next = addr
driver.next = value
# [WRITE] # cs ras cas we dqm : L H L L X
self.cs.next,self.ras.next,self.cas.next,self.we.next = 0,1,0,0
yield clk.posedge
yield clk.posedge
driver.next = None
def getDriver(self):
return self.dq.driver()