##// END OF EJS Templates
MiniSpartan6:...
jeandet -
r681:9d85f9f8f05a default draft
parent child
Show More
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,15
1 vendor_id=0x0403 # Vendor ID
2 product_id=0x6010 # Product ID
3 self_powered=false
4 remote_wakeup=false
5 max_power=0
6 in_is_isochronous=false
7 out_is_isochronous=false
8 suspend_pull_downs=false
9 use_serial=false
10 change_usb_version=false
11 usb_version=0
12 manufacturer="LPP"
13 product="LPP USB SPW Brick"
14 serial=""
15 chb_type=FIFO
@@ -0,0 +1,15
1 vendor_id=0x0403 # Vendor ID
2 product_id=0x6010 # Product ID
3 self_powered=false
4 remote_wakeup=false
5 max_power=0
6 in_is_isochronous=false
7 out_is_isochronous=false
8 suspend_pull_downs=false
9 use_serial=false
10 change_usb_version=false
11 usb_version=0
12 manufacturer="LPP"
13 product="LPP USB SPW Brick"
14 serial=""
15 chb_type=UART
@@ -0,0 +1,145
1 # Clocks
2 NET "CLK50" PERIOD = 20 ns |LOC = "K3";
3 #NET "CLK32" PERIOD = 31.25 ns | LOC = "J4";
4 # LEDs
5 NET "LEDS<0>" LOC="P11" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
6 NET "LEDS<1>" LOC="N9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
7 NET "LEDS<2>" LOC="M9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
8 NET "LEDS<3>" LOC="P9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
9 NET "LEDS<4>" LOC="T8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
10 NET "LEDS<5>" LOC="N8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
11 NET "LEDS<6>" LOC="P8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
12 NET "LEDS<7>" LOC="P7" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
13
14 # DIP Switches
15 NET "SW<1>" LOC="L1" |IOSTANDARD=LVTTL |PULLUP;
16 NET "SW<2>" LOC="L3" |IOSTANDARD=LVTTL |PULLUP;
17 NET "SW<3>" LOC="L4" |IOSTANDARD=LVTTL |PULLUP;
18 NET "SW<4>" LOC="L5" |IOSTANDARD=LVTTL |PULLUP;
19
20 # SDRAM
21 NET "dram_udqm" LOC="F15" |IOSTANDARD=LVTTL;
22 NET "dram_clk" LOC="G16" |IOSTANDARD=LVTTL;
23 NET "dram_cke" LOC="H16" |IOSTANDARD=LVTTL;
24 NET "dram_ba_1" LOC="T14" |IOSTANDARD=LVTTL;
25 NET "dram_ba_0" LOC="R14" |IOSTANDARD=LVTTL;
26 NET "dram_cs_n" LOC="R1" |IOSTANDARD=LVTTL;
27 NET "dram_ras_n" LOC="R2" |IOSTANDARD=LVTTL;
28 NET "dram_cas_n" LOC="T4" |IOSTANDARD=LVTTL;
29 NET "dram_we_n" LOC="R5" |IOSTANDARD=LVTTL;
30 NET "dram_ldqm" LOC="T5" |IOSTANDARD=LVTTL;
31 NET "dram_addr<0>" LOC="T15" |IOSTANDARD=LVTTL;
32 NET "dram_addr<1>" LOC="R16" |IOSTANDARD=LVTTL;
33 NET "dram_addr<2>" LOC="P15" |IOSTANDARD=LVTTL;
34 NET "dram_addr<3>" LOC="P16" |IOSTANDARD=LVTTL;
35 NET "dram_addr<4>" LOC="N16" |IOSTANDARD=LVTTL;
36 NET "dram_addr<5>" LOC="M15" |IOSTANDARD=LVTTL;
37 NET "dram_addr<6>" LOC="M16" |IOSTANDARD=LVTTL;
38 NET "dram_addr<7>" LOC="L16" |IOSTANDARD=LVTTL;
39 NET "dram_addr<8>" LOC="K15" |IOSTANDARD=LVTTL;
40 NET "dram_addr<9>" LOC="K16" |IOSTANDARD=LVTTL;
41 NET "dram_addr<10>" LOC="R15" |IOSTANDARD=LVTTL;
42 NET "dram_addr<11>" LOC="J16" |IOSTANDARD=LVTTL;
43 NET "dram_addr<12>" LOC="H15" |IOSTANDARD=LVTTL;
44 NET "dram_dq<0>" LOC="T13" |IOSTANDARD=LVTTL;
45 NET "dram_dq<1>" LOC="T12" |IOSTANDARD=LVTTL;
46 NET "dram_dq<2>" LOC="R12" |IOSTANDARD=LVTTL;
47 NET "dram_dq<3>" LOC="T9" |IOSTANDARD=LVTTL;
48 NET "dram_dq<4>" LOC="R9" |IOSTANDARD=LVTTL;
49 NET "dram_dq<5>" LOC="T7" |IOSTANDARD=LVTTL;
50 NET "dram_dq<6>" LOC="R7" |IOSTANDARD=LVTTL;
51 NET "dram_dq<7>" LOC="T6" |IOSTANDARD=LVTTL;
52 NET "dram_dq<8>" LOC="F16" |IOSTANDARD=LVTTL;
53 NET "dram_dq<9>" LOC="E15" |IOSTANDARD=LVTTL;
54 NET "dram_dq<10>" LOC="E16" |IOSTANDARD=LVTTL;
55 NET "dram_dq<11>" LOC="D16" |IOSTANDARD=LVTTL;
56 NET "dram_dq<12>" LOC="B16" |IOSTANDARD=LVTTL;
57 NET "dram_dq<13>" LOC="B15" |IOSTANDARD=LVTTL;
58 NET "dram_dq<14>" LOC="C16" |IOSTANDARD=LVTTL;
59 NET "dram_dq<15>" LOC="C15" |IOSTANDARD=LVTTL;
60 #Created by Constraints Editor (xc6slx25-ftg256-3) - 2016/12/08
61 INST "dram_addr(0)" TNM = dram_addr;
62 INST "dram_addr(1)" TNM = dram_addr;
63 INST "dram_addr(2)" TNM = dram_addr;
64 INST "dram_addr(3)" TNM = dram_addr;
65 INST "dram_addr(4)" TNM = dram_addr;
66 INST "dram_addr(5)" TNM = dram_addr;
67 INST "dram_addr(6)" TNM = dram_addr;
68 INST "dram_addr(7)" TNM = dram_addr;
69 INST "dram_addr(8)" TNM = dram_addr;
70 INST "dram_addr(9)" TNM = dram_addr;
71 INST "dram_addr(10)" TNM = dram_addr;
72 INST "dram_addr(11)" TNM = dram_addr;
73 INST "dram_addr(12)" TNM = dram_addr;
74 INST "dram_addr(0)" TNM = dram_out;
75 INST "dram_addr(1)" TNM = dram_out;
76 INST "dram_addr(2)" TNM = dram_out;
77 INST "dram_addr(3)" TNM = dram_out;
78 INST "dram_addr(4)" TNM = dram_out;
79 INST "dram_addr(5)" TNM = dram_out;
80 INST "dram_addr(6)" TNM = dram_out;
81 INST "dram_addr(7)" TNM = dram_out;
82 INST "dram_addr(8)" TNM = dram_out;
83 INST "dram_addr(9)" TNM = dram_out;
84 INST "dram_addr(10)" TNM = dram_out;
85 INST "dram_addr(11)" TNM = dram_out;
86 INST "dram_addr(12)" TNM = dram_out;
87 INST "dram_ba_0" TNM = dram_out;
88 INST "dram_ba_1" TNM = dram_out;
89 INST "dram_cas_n" TNM = dram_out;
90 INST "dram_cke" TNM = dram_out;
91 #INST "dram_clk" TNM = dram_out;
92 INST "dram_cs_n" TNM = dram_out;
93 INST "dram_dq(0)" TNM = dram_out;
94 INST "dram_dq(1)" TNM = dram_out;
95 INST "dram_dq(2)" TNM = dram_out;
96 INST "dram_dq(3)" TNM = dram_out;
97 INST "dram_dq(4)" TNM = dram_out;
98 INST "dram_dq(5)" TNM = dram_out;
99 INST "dram_dq(6)" TNM = dram_out;
100 INST "dram_dq(7)" TNM = dram_out;
101 INST "dram_dq(8)" TNM = dram_out;
102 INST "dram_dq(9)" TNM = dram_out;
103 INST "dram_dq(10)" TNM = dram_out;
104 INST "dram_dq(11)" TNM = dram_out;
105 INST "dram_dq(12)" TNM = dram_out;
106 INST "dram_dq(13)" TNM = dram_out;
107 INST "dram_dq(14)" TNM = dram_out;
108 INST "dram_dq(15)" TNM = dram_out;
109 INST "dram_ldqm" TNM = dram_out;
110 INST "dram_ras_n" TNM = dram_out;
111 INST "dram_udqm" TNM = dram_out;
112 INST "dram_we_n" TNM = dram_out;
113 TIMEGRP "dram_out" OFFSET = OUT 12 ns AFTER "CLK50";
114 INST "dram_dq(0)" TNM = dram_in;
115 INST "dram_dq(1)" TNM = dram_in;
116 INST "dram_dq(2)" TNM = dram_in;
117 INST "dram_dq(3)" TNM = dram_in;
118 INST "dram_dq(4)" TNM = dram_in;
119 INST "dram_dq(5)" TNM = dram_in;
120 INST "dram_dq(6)" TNM = dram_in;
121 INST "dram_dq(7)" TNM = dram_in;
122 INST "dram_dq(8)" TNM = dram_in;
123 INST "dram_dq(9)" TNM = dram_in;
124 INST "dram_dq(10)" TNM = dram_in;
125 INST "dram_dq(11)" TNM = dram_in;
126 INST "dram_dq(12)" TNM = dram_in;
127 INST "dram_dq(13)" TNM = dram_in;
128 INST "dram_dq(14)" TNM = dram_in;
129 INST "dram_dq(15)" TNM = dram_in;
130 TIMEGRP "dram_in" OFFSET = IN 3 ns BEFORE "CLK50" RISING;
131
132 # FTDI
133 NET "FTDI_RXF" LOC="N3" | IOSTANDARD=LVTTL;
134 NET "FTDI_TXE" LOC="N1" | IOSTANDARD=LVTTL;
135 NET "FTDI_SIWUA" LOC="M3" | IOSTANDARD=LVTTL;
136 NET "FTDI_WR" LOC="M2" | IOSTANDARD=LVTTL;
137 NET "FTDI_RD" LOC="M1" | IOSTANDARD=LVTTL;
138 NET "FTDI_D<0>" LOC="M7" | IOSTANDARD=LVTTL;
139 NET "FTDI_D<1>" LOC="N6" | IOSTANDARD=LVTTL;
140 NET "FTDI_D<2>" LOC="M6" | IOSTANDARD=LVTTL;
141 NET "FTDI_D<3>" LOC="P5" | IOSTANDARD=LVTTL;
142 NET "FTDI_D<4>" LOC="N5" | IOSTANDARD=LVTTL;
143 NET "FTDI_D<5>" LOC="P4" | IOSTANDARD=LVTTL;
144 NET "FTDI_D<6>" LOC="P2" | IOSTANDARD=LVTTL;
145 NET "FTDI_D<7>" LOC="P1" | IOSTANDARD=LVTTL;
@@ -0,0 +1,77
1 VHDLIB=../..
2 SELFDIR := $(dir $(lastword $(MAKEFILE_LIST)))
3 SCRIPTSDIR=$(VHDLIB)/scripts/
4 GRLIB := $(shell sh $(VHDLIB)/scripts/lpp_relpath.sh)
5 TOP=leon3mp
6 BOARD=MiniSpartan6p
7 DESIGN=leon3-MiniSpartan6p
8 include $(VHDLIB)/boards/$(BOARD)/Makefile.inc
9 DEVICE=$(PART)-$(PACKAGE)$(SPEED)
10 #UCF=$(VHDLIB)/boards/$(BOARD)/default.ucf
11 UCF=$(VHDLIB)/boards/$(BOARD)/with-fifo.ucf
12 UCF_PLANAHEAD=$(UCF)
13 QSF=$(GRLIB)/boards/$(BOARD)/$(TOP).qsf
14 EFFORT=high
15 XSTOPT=-uc leon3mp.xcf
16 SYNPOPT="set_option -pipe 1; set_option -retiming 1; set_option -write_apr_constraint 0"
17
18
19 VHDLOPTSYNFILES = sdctrl16.vhd config.vhd leon3mp.vhd
20
21 VHDLSIMFILES=mt48lc16m16a2.vhd testbench.vhd
22
23 SIMTOP=testbench
24 SDCFILE=$(GRLIB)/boards/$(BOARD)/default.sdc
25 BITGEN=$(VHDLIB)/boards/$(BOARD)/default.ut
26
27 TECHLIBS = unisim
28
29 LIBSKIP = core1553bbc core1553brm core1553brt gr1553 corePCIF \
30 tmtc openchip hynix ihp gleichmann usbhc opencores fmf ftlib gsi
31
32 DIRSKIP = b1553 pcif leon2 leon2ft crypto satcan ddr usb ata i2c \
33 pci grusbhc haps slink ascs can pwm greth coremp7 ac97 atf \
34 grlfpc \
35 ./dsp/lpp_fft_rtax \
36 ./amba_lcd_16x2_ctrlr \
37 ./general_purpose/lpp_AMR \
38 ./general_purpose/lpp_balise \
39 ./general_purpose/lpp_delay \
40 ./lpp_bootloader \
41 ./lpp_sim/CY7C1061DV33 \
42 ./lpp_uart \
43 ./dsp/lpp_fft \
44 ./lpp_leon3_soc \
45 ./lpp_debug_lfr
46
47 FILESKIP = i2cmst.vhd \
48 APB_MULTI_DIODE.vhd \
49 APB_MULTI_DIODE.vhd \
50 Top_MatrixSpec.vhd \
51 APB_FFT.vhd \
52 lpp_lfr_ms_FFT.vhd \
53 lpp_lfr_apbreg.vhd \
54 CoreFFT.vhd \
55 lpp_lfr_ms.vhd \
56 lpp_lfr_sim_pkg.vhd \
57 mtie_maps.vhd \
58 ftsrctrlc.vhd \
59 ftsdctrl.vhd \
60 ftsrctrl8.vhd \
61 ftmctrl.vhd \
62 ftsdctrl64.vhd \
63 ftahbram.vhd \
64 ftahbram2.vhd \
65 sramft.vhd \
66 nandfctrlx.vhd
67
68 include $(GRLIB)/bin/Makefile
69
70 ################## project specific targets ##########################
71
72 load-ram:
73 xc3sprog -c ftdi -p0 leon3mp.bit
74
75 load-flash:
76 xc3sprog -c ftdi -p0 $(VHDLIB)/boards/$(BOARD)/bscan_spi_s6lx25_ftg256.bit
77 xc3sprog -c ftdi -I leon3mp.bit
@@ -0,0 +1,66
1 This LEON3 design is tailored to the Scarab Hardware [MiniSpartan6+](https://www.scarabhardware.com/minispartan6/) board.
2
3 Simulation and synthesis
4 ------------------------
5
6 This design tries to use as much as possible free (as in freedom) tools and at least free (as in free beer) when impossible.
7
8
9 Note that the simulation doesn't work as expected yet.
10
11
12 To build the design:
13 ```bash
14 make ise
15 ```
16
17 To load into FPGA RAM:
18 ```bash
19 make load-ram
20 ```
21
22 To load into FPGA Flash:
23 ```bash
24 make load-flash
25 ```
26
27 Design specifics
28 ----------------
29
30 * The AHB and processor is clocked from the 50 MHz clock.
31
32 * The SDRAM is working with the sdctrl16 memory controller taken from leon3-altera-de2-ep2c35 design.
33
34 * The UART DSU interface ie enabled and connected to interface B of ft2232H chip.
35 Start GRMON with -uart /dev/ttyUSB1
36
37 * Output from GRMON2 should look similar to this:
38
39 ```bash
40 GRMON2 LEON debug monitor v2.0.80-beta 64-bit eval version
41
42 Copyright (C) 2016 Cobham Gaisler - All rights reserved.
43 For latest updates, go to http://www.gaisler.com/
44 Comments or bug-reports to support@gaisler.com
45
46 This eval version will expire on 18/04/2017
47
48 using port /dev/ttyUSB1 @ 115200 baud
49 GRLIB build version: 4164
50 Detected frequency: 50 MHz
51
52 Component Vendor
53 LEON3 SPARC V8 Processor Cobham Gaisler
54 AHB Debug UART Cobham Gaisler
55 AHB/APB Bridge Cobham Gaisler
56 LEON3 Debug Support Unit Cobham Gaisler
57 PC133 SDRAM Controller Cobham Gaisler
58 Multi-processor Interrupt Ctrl. Cobham Gaisler
59 Modular Timer Unit Cobham Gaisler
60 General Purpose I/O port Cobham Gaisler
61
62 Use command 'info sys' to print a detailed report of attached cores
63
64 grmon2>
65
66 ``` No newline at end of file
@@ -0,0 +1,166
1
2
3
4 -----------------------------------------------------------------------------
5 -- LEON3 Demonstration design test bench configuration
6 -- Copyright (C) 2009 Aeroflex Gaisler
7 ------------------------------------------------------------------------------
8
9
10 library techmap;
11 use techmap.gencomp.all;
12
13 package config is
14 -- Technology and synthesis options
15 constant CFG_FABTECH : integer := spartan6;
16 constant CFG_MEMTECH : integer := spartan6;
17 constant CFG_PADTECH : integer := spartan6;
18 constant CFG_TRANSTECH : integer := GTP0;
19 constant CFG_NOASYNC : integer := 0;
20 constant CFG_SCAN : integer := 0;
21 -- Clock generator
22 constant CFG_CLKTECH : integer := spartan6;
23 constant CFG_CLKMUL : integer := (3);
24 constant CFG_CLKDIV : integer := (2);
25 constant CFG_OCLKDIV : integer := 1;
26 constant CFG_OCLKBDIV : integer := 0;
27 constant CFG_OCLKCDIV : integer := 0;
28 constant CFG_PCIDLL : integer := 0;
29 constant CFG_PCISYSCLK: integer := 0;
30 constant CFG_CLK_NOFB : integer := 0;
31 -- LEON3 processor core
32 constant CFG_LEON3 : integer := 1;
33 constant CFG_NCPU : integer := (1);
34 constant CFG_NWIN : integer := (8);
35 constant CFG_V8 : integer := 2 + 4*0;
36 constant CFG_MAC : integer := 0;
37 constant CFG_BP : integer := 1;
38 constant CFG_SVT : integer := 1;
39 constant CFG_RSTADDR : integer := 16#00000#;
40 constant CFG_LDDEL : integer := (2);
41 constant CFG_NOTAG : integer := 1;
42 constant CFG_NWP : integer := (0);
43 constant CFG_PWD : integer := 0*2;
44 constant CFG_FPU : integer := 0 + 16*0 + 32*0;
45 constant CFG_GRFPUSH : integer := 0;
46 constant CFG_ICEN : integer := 1;
47 constant CFG_ISETS : integer := 1;
48 constant CFG_ISETSZ : integer := 8;
49 constant CFG_ILINE : integer := 8;
50 constant CFG_IREPL : integer := 0;
51 constant CFG_ILOCK : integer := 0;
52 constant CFG_ILRAMEN : integer := 0;
53 constant CFG_ILRAMADDR: integer := 16#8E#;
54 constant CFG_ILRAMSZ : integer := 1;
55 constant CFG_DCEN : integer := 1;
56 constant CFG_DSETS : integer := 1;
57 constant CFG_DSETSZ : integer := 8;
58 constant CFG_DLINE : integer := 8;
59 constant CFG_DREPL : integer := 0;
60 constant CFG_DLOCK : integer := 0;
61 constant CFG_DSNOOP : integer := 0 + 0*2 + 4*0;
62 constant CFG_DFIXED : integer := 16#0#;
63 constant CFG_DLRAMEN : integer := 0;
64 constant CFG_DLRAMADDR: integer := 16#8F#;
65 constant CFG_DLRAMSZ : integer := 1;
66 constant CFG_MMUEN : integer := 0;
67 constant CFG_ITLBNUM : integer := 8;
68 constant CFG_DTLBNUM : integer := 2;
69 constant CFG_TLB_TYPE : integer := 1 + 0*2;
70 constant CFG_TLB_REP : integer := 1;
71 constant CFG_MMU_PAGE : integer := 0;
72 constant CFG_DSU : integer := 1;
73 constant CFG_ITBSZ : integer := 0 + 64*0;
74 constant CFG_ATBSZ : integer := 0;
75 constant CFG_AHBPF : integer := 0;
76 constant CFG_LEON3FT_EN : integer := 0;
77 constant CFG_IUFT_EN : integer := 0;
78 constant CFG_FPUFT_EN : integer := 0;
79 constant CFG_RF_ERRINJ : integer := 0;
80 constant CFG_CACHE_FT_EN : integer := 0;
81 constant CFG_CACHE_ERRINJ : integer := 0;
82 constant CFG_LEON3_NETLIST: integer := 0;
83 constant CFG_DISAS : integer := 0 + 0;
84 constant CFG_PCLOW : integer := 2;
85 constant CFG_STAT_ENABLE : integer := 0;
86 constant CFG_STAT_CNT : integer := 1;
87 constant CFG_STAT_NMAX : integer := 0;
88 constant CFG_STAT_DSUEN : integer := 0;
89 constant CFG_NP_ASI : integer := 0;
90 constant CFG_WRPSR : integer := 0;
91 constant CFG_ALTWIN : integer := 0;
92 constant CFG_REX : integer := 0;
93 -- AMBA settings
94 constant CFG_DEFMST : integer := (0);
95 constant CFG_RROBIN : integer := 1;
96 constant CFG_SPLIT : integer := 1;
97 constant CFG_FPNPEN : integer := 0;
98 constant CFG_AHBIO : integer := 16#FFF#;
99 constant CFG_APBADDR : integer := 16#800#;
100 constant CFG_AHB_MON : integer := 0;
101 constant CFG_AHB_MONERR : integer := 0;
102 constant CFG_AHB_MONWAR : integer := 0;
103 constant CFG_AHB_DTRACE : integer := 0;
104 -- DSU UART
105 constant CFG_AHB_UART : integer := 0;
106 -- JTAG based DSU interface
107 constant CFG_AHB_JTAG : integer := 1;
108 -- Xilinx MIG
109 constant CFG_MIG_DDR2 : integer := 1;
110 constant CFG_MIG_RANKS : integer := (1);
111 constant CFG_MIG_COLBITS : integer := (10);
112 constant CFG_MIG_ROWBITS : integer := (13);
113 constant CFG_MIG_BANKBITS: integer := (2);
114 constant CFG_MIG_HMASK : integer := 16#FC0#;
115 -- AHB ROM
116 constant CFG_AHBROMEN : integer := 1;
117 constant CFG_AHBROPIP : integer := 0;
118 constant CFG_AHBRODDR : integer := 16#000#;
119 constant CFG_ROMADDR : integer := 16#100#;
120 constant CFG_ROMMASK : integer := 16#E00# + 16#100#;
121 -- AHB RAM
122 constant CFG_AHBRAMEN : integer := 1;
123 constant CFG_AHBRSZ : integer := 4;
124 constant CFG_AHBRADDR : integer := 16#A00#;
125 constant CFG_AHBRPIPE : integer := 0;
126 -- UART 1
127 constant CFG_UART1_ENABLE : integer := 1;
128 constant CFG_UART1_FIFO : integer := 4;
129 -- LEON3 interrupt controller
130 constant CFG_IRQ3_ENABLE : integer := 1;
131 constant CFG_IRQ3_NSEC : integer := 0;
132 -- Modular timer
133 constant CFG_GPT_ENABLE : integer := 1;
134 constant CFG_GPT_NTIM : integer := (2);
135 constant CFG_GPT_SW : integer := (8);
136 constant CFG_GPT_TW : integer := (32);
137 constant CFG_GPT_IRQ : integer := (8);
138 constant CFG_GPT_SEPIRQ : integer := 1;
139 constant CFG_GPT_WDOGEN : integer := 0;
140 constant CFG_GPT_WDOG : integer := 16#0#;
141 -- GPIO port
142 constant CFG_GRGPIO_ENABLE : integer := 0;
143 constant CFG_GRGPIO_IMASK : integer := 16#0000#;
144 constant CFG_GRGPIO_WIDTH : integer := 1;
145
146 -- SPI controller
147 constant CFG_SPICTRL_ENABLE : integer := 1;
148 constant CFG_SPICTRL_NUM : integer := (1);
149 constant CFG_SPICTRL_SLVS : integer := (1);
150 constant CFG_SPICTRL_FIFO : integer := (2);
151 constant CFG_SPICTRL_SLVREG : integer := 1;
152 constant CFG_SPICTRL_ODMODE : integer := 1;
153 constant CFG_SPICTRL_AM : integer := 0;
154 constant CFG_SPICTRL_ASEL : integer := 0;
155 constant CFG_SPICTRL_TWEN : integer := 0;
156 constant CFG_SPICTRL_MAXWLEN : integer := (0);
157 constant CFG_SPICTRL_SYNCRAM : integer := 0;
158 constant CFG_SPICTRL_FT : integer := 0;
159
160 -- GRLIB debugging
161 constant CFG_DUART : integer := 0;
162
163
164 constant CFG_AHB_FTDI : integer := 1;
165 constant CFG_FTDI_LOOPBACK : integer := 0;
166 end;
@@ -0,0 +1,340
1
2
3 library ieee;
4 use ieee.std_logic_1164.all;
5 USE IEEE.NUMERIC_STD.ALL;
6 library grlib;
7 use grlib.amba.all;
8 use grlib.stdlib.all;
9 use grlib.devices.all;
10 library techmap;
11 use techmap.gencomp.all;
12 use techmap.allclkgen.all;
13 library gaisler;
14 use gaisler.memctrl.all;
15 use gaisler.leon3.all;
16 use gaisler.uart.all;
17 use gaisler.misc.all;
18 use gaisler.jtag.all;
19 --pragma translate_off
20 use gaisler.sim.all;
21 --pragma translate_on
22 library lpp;
23 use lpp.lpp_usb.all;
24
25 use work.config.all;
26
27 library unisim;
28 use unisim.vcomponents.all;
29
30 entity leon3mp is
31 generic (
32 fabtech : integer := CFG_FABTECH;
33 memtech : integer := CFG_MEMTECH;
34 padtech : integer := CFG_PADTECH;
35 clktech : integer := CFG_CLKTECH;
36 disas : integer := CFG_DISAS; -- Enable disassembly to console
37 dbguart : integer := CFG_DUART; -- Print UART on console
38 pclow : integer := CFG_PCLOW
39 );
40 port (
41 CLK50 : in std_logic;
42 LEDS : inout std_logic_vector(7 downto 0);
43 SW : in std_logic_vector(4 downto 1);
44 dram_addr : out std_logic_vector(12 downto 0);
45 dram_ba_0 : out std_logic;
46 dram_ba_1 : out std_logic;
47 dram_dq : inout std_logic_vector(15 downto 0);
48
49 dram_clk : out std_logic;
50 dram_cke : out std_logic;
51 dram_cs_n : out std_logic;
52 dram_we_n : out std_logic; -- sdram write enable
53 dram_ras_n : out std_logic; -- sdram ras
54 dram_cas_n : out std_logic; -- sdram cas
55 dram_ldqm : out std_logic; -- sdram ldqm
56 dram_udqm : out std_logic; -- sdram udqm
57 uart_txd : out std_logic; -- DSU tx data
58 uart_rxd : in std_logic; -- DSU rx data
59
60 FTDI_RXF : in std_logic;
61 FTDI_TXE : in std_logic;
62 FTDI_SIWUA : out std_logic;
63 FTDI_WR : out std_logic;
64 FTDI_RD : out std_logic;
65 FTDI_D : inout std_logic_vector(7 downto 0)
66
67 );
68 end;
69
70 architecture rtl of leon3mp is
71 signal resetn : std_logic;
72 signal clkm, rstn, rstraw, rst : std_logic;
73 signal clkm_inv : std_logic := '0';
74
75 signal cptr : std_logic_vector(29 downto 0);
76 constant BOARD_FREQ : integer := 25000; -- CLK input frequency in KHz
77 constant CPU_FREQ : integer := BOARD_FREQ * CFG_CLKMUL / CFG_CLKDIV; -- cpu frequency in KHz
78 signal sdi : sdctrl_in_type;
79 signal sdo : sdctrl_out_type;
80
81 --AMBA bus standard interface signals--
82 signal apbi : apb_slv_in_type;
83 signal apbo : apb_slv_out_vector := (others => apb_none);
84 signal ahbsi : ahb_slv_in_type;
85 signal ahbso : ahb_slv_out_vector := (others => ahbs_none);
86 signal ahbmi : ahb_mst_in_type;
87 signal ahbmo : ahb_mst_out_vector := (others => ahbm_none);
88
89 signal tck, tckn, tms, tdi, tdo : std_ulogic;
90
91 signal cgi : clkgen_in_type;
92 signal cgo : clkgen_out_type;
93
94 signal dui : uart_in_type;
95 signal duo : uart_out_type;
96
97 signal irqi : irq_in_vector(0 to CFG_NCPU-1);
98 signal irqo : irq_out_vector(0 to CFG_NCPU-1);
99
100 signal dbgi : l3_debug_in_vector(0 to CFG_NCPU-1);
101 signal dbgo : l3_debug_out_vector(0 to CFG_NCPU-1);
102
103 signal dsui : dsu_in_type;
104 signal dsuo : dsu_out_type;
105
106
107 signal gpti : gptimer_in_type;
108
109 signal gpioi_0 : gpio_in_type;
110 signal gpioo_0 : gpio_out_type;
111
112 signal dsubren : std_logic :='0';
113
114
115 signal FTDI_D_in : std_logic_vector(7 downto 0);
116 signal FTDI_D_out : std_logic_vector(7 downto 0);
117 signal FTDI_drive : std_logic;
118
119
120 component sdctrl16
121 generic (
122 hindex : integer := 0;
123 haddr : integer := 0;
124 hmask : integer := 16#f00#;
125 ioaddr : integer := 16#000#;
126 iomask : integer := 16#fff#;
127 wprot : integer := 0;
128 invclk : integer := 0;
129 fast : integer := 0;
130 pwron : integer := 0;
131 sdbits : integer := 16;
132 oepol : integer := 0;
133 pageburst : integer := 0;
134 mobile : integer := 0
135 );
136 port (
137 rst : in std_ulogic;
138 clk : in std_ulogic;
139 ahbsi : in ahb_slv_in_type;
140 ahbso : out ahb_slv_out_type;
141 sdi : in sdctrl_in_type;
142 sdo : out sdctrl_out_type
143 );
144 end component;
145
146 begin
147 resetn <= SW(1);
148
149 clk_pad : clkpad generic map (tech => padtech) port map (CLK50, clkm);
150 clkm_inv <= not clkm;
151
152 resetn_pad : inpad generic map (tech => padtech) port map (resetn, rst);
153 rst0 : rstgen -- reset generator (reset is active LOW)
154 port map (rst, clkm, '1', rstn, rstraw);
155
156
157 ----------------------------------------------------------------------
158 --- AHB CONTROLLER --------------------------------------------------
159 ----------------------------------------------------------------------
160
161 ahb0 : ahbctrl -- AHB arbiter/multiplexer
162 generic map (defmast => CFG_DEFMST, split => CFG_SPLIT,
163 rrobin => CFG_RROBIN, ioaddr => CFG_AHBIO,
164 nahbm => CFG_NCPU+CFG_AHB_FTDI+CFG_AHB_UART+CFG_AHB_JTAG, nahbs => 8)
165
166 port map (rstn, clkm, ahbmi, ahbmo, ahbsi, ahbso);
167
168 ----------------------------------------------------------------------
169 ----- LEON3 processor and DSU ---------------------------------------
170 ----------------------------------------------------------------------
171
172 cpu : for i in 0 to CFG_NCPU-1 generate
173 nosh : if CFG_GRFPUSH = 0 generate
174 u0 : leon3s -- LEON3 processor
175 generic map (i, fabtech, memtech, CFG_NWIN, CFG_DSU, CFG_FPU*(1-CFG_GRFPUSH), CFG_V8,
176 0, CFG_MAC, pclow, CFG_NOTAG, CFG_NWP, CFG_ICEN, CFG_IREPL, CFG_ISETS, CFG_ILINE,
177 CFG_ISETSZ, CFG_ILOCK, CFG_DCEN, CFG_DREPL, CFG_DSETS, CFG_DLINE, CFG_DSETSZ,
178 CFG_DLOCK, CFG_DSNOOP, CFG_ILRAMEN, CFG_ILRAMSZ, CFG_ILRAMADDR, CFG_DLRAMEN,
179 CFG_DLRAMSZ, CFG_DLRAMADDR, CFG_MMUEN, CFG_ITLBNUM, CFG_DTLBNUM, CFG_TLB_TYPE, CFG_TLB_REP,
180 CFG_LDDEL, disas, CFG_ITBSZ, CFG_PWD, CFG_SVT, CFG_RSTADDR, CFG_NCPU-1,
181 0, 0, CFG_MMU_PAGE, CFG_BP, CFG_NP_ASI, CFG_WRPSR)
182 port map (clkm, rstn, ahbmi, ahbmo(i), ahbsi, ahbso,
183 irqi(i), irqo(i), dbgi(i), dbgo(i));
184 end generate;
185 end generate;
186
187 --ledr[0] lit when leon 3 debugvector signals error
188 dsugen : if CFG_DSU = 1 generate
189 dsu0 : dsu3 -- LEON3 Debug Support Unit (slave)
190 generic map (hindex => 2, haddr => 16#900#, hmask => 16#F00#,
191 ncpu => CFG_NCPU, tbits => 30, tech => memtech, irq => 0, kbytes => CFG_ATBSZ)
192 port map (rstn, clkm, ahbmi, ahbsi, ahbso(2), dbgo, dbgi, dsui, dsuo);
193 dsui.enable <= '1';
194
195 end generate;
196 nodsu : if CFG_DSU = 0 generate
197 ahbso(2) <= ahbs_none; dsuo.tstop <= '0'; dsuo.active <= '0'; --no timer freeze, no light.
198 end generate;
199
200 dcomgen : if CFG_AHB_UART = 1 generate
201 dcom0: ahbuart -- Debug UART
202 generic map (hindex => CFG_NCPU, pindex => 7, paddr => 7)
203 port map (rstn, clkm, dui, duo, apbi, apbo(7), ahbmi, ahbmo(CFG_NCPU));
204 end generate;
205 uart_txd <= duo.txd;
206 dui.rxd <= uart_rxd;
207
208 ahbjtaggen0 :if CFG_AHB_JTAG = 1 generate
209 ahbjtag0 : ahbjtag generic map(tech => fabtech, hindex => CFG_NCPU+CFG_AHB_UART)
210 port map(rstn, clkm, tck, tms, tdi, tdo, ahbmi, ahbmo(CFG_NCPU+CFG_AHB_UART),
211 open, open, open, open, open, open, open, '0');
212 end generate;
213
214
215 ----------------------------------------------------------------------
216 --- Memory controllers ----------------------------------------------
217 ----------------------------------------------------------------------
218
219
220 sdc : sdctrl16 generic map (hindex => 3, haddr => 16#400#, hmask => 16#FE0#, -- hmask => 16#C00#,
221 ioaddr => 1, fast => 0, pwron => 0, invclk => 0,
222 sdbits => 16, pageburst => 2)
223 port map (rstn, clkm, ahbsi, ahbso(3), sdi, sdo);
224 sa_pad : outpadv generic map (width => 13, tech => padtech)
225 port map (dram_addr, sdo.address(14 downto 2));
226 ba0_pad : outpad generic map (tech => padtech)
227 port map (dram_ba_0, sdo.address(15));
228 ba1_pad : outpad generic map (tech => padtech)
229 port map (dram_ba_1, sdo.address(16));
230 sd_pad : iopadvv generic map (width => 16, tech => padtech)
231 port map (dram_dq(15 downto 0), sdo.data(15 downto 0), sdo.vbdrive(15 downto 0), sdi.data(15 downto 0));
232 sdcke_pad : outpad generic map (tech => padtech)
233 port map (dram_cke, sdo.sdcke(0));
234 sdwen_pad : outpad generic map (tech => padtech)
235 port map (dram_we_n, sdo.sdwen);
236 sdcsn_pad : outpad generic map (tech => padtech)
237 port map (dram_cs_n, sdo.sdcsn(0));
238 sdras_pad : outpad generic map (tech => padtech)
239 port map (dram_ras_n, sdo.rasn);
240 sdcas_pad : outpad generic map (tech => padtech)
241 port map (dram_cas_n, sdo.casn);
242 sdldqm_pad : outpad generic map (tech => padtech)
243 port map (dram_ldqm, sdo.dqm(0) );
244 sdudqm_pad : outpad generic map (tech => padtech)
245 port map (dram_udqm, sdo.dqm(1));
246 dram_clk_pad : outpad generic map (tech => padtech)
247 port map (dram_clk, clkm_inv);
248
249 ----------------------------------------------------------------------
250 --- APB Bridge and various periherals -------------------------------
251 ----------------------------------------------------------------------
252
253 apb0 : apbctrl -- AHB/APB bridge
254 generic map (hindex => 1, haddr => CFG_APBADDR)
255 port map (rstn, clkm, ahbsi, ahbso(1), apbi, apbo );
256
257 ----------------------------------------------------------------------------------------
258
259 irqctrl : if CFG_IRQ3_ENABLE /= 0 generate
260 irqctrl0 : irqmp -- interrupt controller
261 generic map (pindex => 2, paddr => 2, ncpu => CFG_NCPU)
262 port map (rstn, clkm, apbi, apbo(2), irqo, irqi);
263 end generate;
264 irq3 : if CFG_IRQ3_ENABLE = 0 generate
265 x : for i in 0 to CFG_NCPU-1 generate irqi(i).irl <= "0000"; end generate;
266 apbo(2) <= apb_none;
267 end generate;
268
269 --Timer unit, generates interrupts when a timer underflow.
270 gpt : if CFG_GPT_ENABLE /= 0 generate
271 timer0 : gptimer -- timer unit
272 generic map (pindex => 3, paddr => 3, pirq => CFG_GPT_IRQ,
273 sepirq => CFG_GPT_SEPIRQ, sbits => CFG_GPT_SW, ntimers => CFG_GPT_NTIM,
274 nbits => CFG_GPT_TW)
275 port map (rstn, clkm, apbi, apbo(3), gpti, open);
276 gpti <= gpti_dhalt_drive(dsuo.tstop);
277 end generate;
278 notim : if CFG_GPT_ENABLE = 0 generate apbo(3) <= apb_none; end generate;
279
280 gpio0 : if CFG_GRGPIO_ENABLE /= 0 generate -- GR GPIO0 unit
281 grgpio0: grgpio
282 generic map( pindex => 9, paddr => 9, imask => CFG_GRGPIO_IMASK, nbits => 8)
283 port map( rstn, clkm, apbi, apbo(9), gpioi_0, gpioo_0);
284 pio_pads : for i in 0 to 7 generate
285 pio_pad : iopad generic map (tech => padtech)
286 port map (LEDS(i), gpioo_0.dout(i), gpioo_0.oen(i), gpioi_0.din(i));
287 end generate;
288 end generate;
289 nogpio0: if CFG_GRGPIO_ENABLE = 0 generate apbo(9) <= apb_none;
290 LEDS(5 downto 0) <= FTDI_D_in(5 downto 0);
291 LEDS(7 downto 6) <= FTDI_RXF & FTDI_TXE;
292
293 end generate;
294
295 ahb_ftdi0: if CFG_AHB_FTDI /=0 generate
296 ftdi_dcom: ahb_ftdi_fifo
297 generic map (oepol => 0 , hindex => CFG_NCPU+CFG_AHB_FTDI+CFG_AHB_UART+CFG_AHB_JTAG )
298 port map (
299 clk => clkm,
300 rstn => rstn,
301 ahbi => ahbmi,
302 ahbo => ahbmo(CFG_NCPU+CFG_AHB_FTDI+CFG_AHB_UART+CFG_AHB_JTAG),
303
304 FTDI_RXF => FTDI_RXF,
305 FTDI_TXE => FTDI_TXE,
306 FTDI_SIWUA => FTDI_SIWUA,
307 FTDI_WR => FTDI_WR,
308 FTDI_RD => FTDI_RD,
309 FTDI_D_in => FTDI_D_in,
310 FTDI_D_out => FTDI_D_out,
311 FTDI_D_drive => FTDI_drive
312 );
313 end generate;
314
315 ftdi_loopback0: if CFG_FTDI_LOOPBACK /=0 generate
316 ftdi_loopback: ftdi_async_fifo_loopback
317 generic map (oepol => 0 )
318 port map (
319 clk => clkm,
320 rstn => rstn,
321
322 FTDI_RXF => FTDI_RXF,
323 FTDI_TXE => FTDI_TXE,
324 FTDI_SIWUA => FTDI_SIWUA,
325 FTDI_WR => FTDI_WR,
326 FTDI_RD => FTDI_RD,
327 FTDI_D_in => FTDI_D_in,
328 FTDI_D_out => FTDI_D_out,
329 FTDI_D_drive => FTDI_drive
330 );
331 end generate;
332
333
334 fifo_pad : iopadv generic map (width => 8, tech => padtech)
335 port map (FTDI_D(7 downto 0), FTDI_D_out(7 downto 0), FTDI_drive, FTDI_D_in(7 downto 0));
336
337
338
339 end rtl;
340
@@ -0,0 +1,4
1
2 NET CLK50 PERIOD = 20.0 ;
3
4
This diff has been collapsed as it changes many lines, (1550 lines changed) Show them Hide them
@@ -0,0 +1,1550
1
2 --*****************************************************************************
3 --
4 -- Micron Semiconductor Products, Inc.
5 --
6 -- Copyright 1997, Micron Semiconductor Products, Inc.
7 -- All rights reserved.
8 --
9 --*****************************************************************************
10
11 -- pragma translate_off
12
13 library ieee;
14 use ieee.std_logic_1164.ALL;
15 use std.textio.all;
16
17 PACKAGE mti_pkg IS
18
19 FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC;
20 FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER;
21 FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER;
22 FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER;
23 PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR);
24
25
26 END mti_pkg;
27
28 PACKAGE BODY mti_pkg IS
29
30 -- Convert BIT to STD_LOGIC
31 FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC IS
32 BEGIN
33 CASE s IS
34 WHEN '0' => RETURN ('0');
35 WHEN '1' => RETURN ('1');
36 WHEN OTHERS => RETURN ('0');
37 END CASE;
38 END;
39
40 -- Convert STD_LOGIC to INTEGER
41 FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS
42 VARIABLE result : INTEGER := 0;
43 VARIABLE weight : INTEGER := 1;
44 BEGIN
45 IF input = '1' THEN
46 result := weight;
47 ELSE
48 result := 0; -- if unknowns, default to logic 0
49 END IF;
50 RETURN result;
51 END TO_INTEGER;
52
53 -- Convert BIT_VECTOR to INTEGER
54 FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS
55 VARIABLE result : INTEGER := 0;
56 VARIABLE weight : INTEGER := 1;
57 BEGIN
58 FOR i IN input'LOW TO input'HIGH LOOP
59 IF input(i) = '1' THEN
60 result := result + weight;
61 ELSE
62 result := result + 0; -- if unknowns, default to logic 0
63 END IF;
64 weight := weight * 2;
65 END LOOP;
66 RETURN result;
67 END TO_INTEGER;
68
69 -- Convert STD_LOGIC_VECTOR to INTEGER
70 FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS
71 VARIABLE result : INTEGER := 0;
72 VARIABLE weight : INTEGER := 1;
73 BEGIN
74 FOR i IN input'LOW TO input'HIGH LOOP
75 IF input(i) = '1' THEN
76 result := result + weight;
77 ELSE
78 result := result + 0; -- if unknowns, default to logic 0
79 END IF;
80 weight := weight * 2;
81 END LOOP;
82 RETURN result;
83 END TO_INTEGER;
84
85 -- Conver INTEGER to BIT_VECTOR
86 PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS
87 VARIABLE work,offset,outputlen,j : INTEGER := 0;
88 BEGIN
89 --length of vector
90 IF output'LENGTH > 32 THEN --'
91 outputlen := 32;
92 offset := output'LENGTH - 32; --'
93 IF input >= 0 THEN
94 FOR i IN offset-1 DOWNTO 0 LOOP
95 output(output'HIGH - i) := '0'; --'
96 END LOOP;
97 ELSE
98 FOR i IN offset-1 DOWNTO 0 LOOP
99 output(output'HIGH - i) := '1'; --'
100 END LOOP;
101 END IF;
102 ELSE
103 outputlen := output'LENGTH; --'
104 END IF;
105 --positive value
106 IF (input >= 0) THEN
107 work := input;
108 j := outputlen - 1;
109 FOR i IN 1 to 32 LOOP
110 IF j >= 0 then
111 IF (work MOD 2) = 0 THEN
112 output(output'HIGH-j-offset) := '0'; --'
113 ELSE
114 output(output'HIGH-j-offset) := '1'; --'
115 END IF;
116 END IF;
117 work := work / 2;
118 j := j - 1;
119 END LOOP;
120 IF outputlen = 32 THEN
121 output(output'HIGH) := '0'; --'
122 END IF;
123 --negative value
124 ELSE
125 work := (-input) - 1;
126 j := outputlen - 1;
127 FOR i IN 1 TO 32 LOOP
128 IF j>= 0 THEN
129 IF (work MOD 2) = 0 THEN
130 output(output'HIGH-j-offset) := '1'; --'
131 ELSE
132 output(output'HIGH-j-offset) := '0'; --'
133 END IF;
134 END IF;
135 work := work / 2;
136 j := j - 1;
137 END LOOP;
138 IF outputlen = 32 THEN
139 output(output'HIGH) := '1'; --'
140 END IF;
141 END IF;
142 END TO_BITVECTOR;
143
144 END mti_pkg;
145
146 -----------------------------------------------------------------------------------------
147 --
148 -- File Name: MT48LC16M16A2.VHD
149 -- Version: 0.0g
150 -- Date: June 29th, 2000
151 -- Model: Behavioral
152 -- Simulator: Model Technology (PC version 5.3 PE)
153 --
154 -- Dependencies: None
155 --
156 -- Author: Son P. Huynh
157 -- Email: sphuynh@micron.com
158 -- Phone: (208) 368-3825
159 -- Company: Micron Technology, Inc.
160 -- Part Number: MT48LC16M16A2 (4Mb x 16 x 4 Banks)
161 --
162 -- Description: Micron 256Mb SDRAM
163 --
164 -- Limitation: - Doesn't check for 4096-cycle refresh --'
165 --
166 -- Note: - Set simulator resolution to "ps" accuracy
167 --
168 -- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
169 -- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
170 -- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
171 -- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
172 --
173 -- Copyright (c) 1998 Micron Semiconductor Products, Inc.
174 -- All rights researved
175 --
176 -- Rev Author Phone Date Changes
177 -- ---- ---------------------------- ---------- -------------------------------------
178 -- 0.0g Son Huynh 208-368-3825 06/29/2000 Add Load/Dump memory array
179 -- Micron Technology Inc. Modify tWR + tRAS timing check
180 --
181 -- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto)
182 -- Micron Technology Inc. Fix tWR = 15 ns (Manual)
183 -- Fix tRP (Autoprecharge to AutoRefresh)
184 --
185 -- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP
186 -- Micron Technology Inc. Fix tRC check in Load Mode Register
187 --
188 -- 0.0b Son P. Huynh 208-368-3825 01/06/1998 Derive from 64Mb SDRAM model
189 -- Micron Technology Inc.
190 --
191 -----------------------------------------------------------------------------------------
192
193 LIBRARY STD;
194 USE STD.TEXTIO.ALL;
195 LIBRARY IEEE;
196 USE IEEE.STD_LOGIC_1164.ALL;
197 LIBRARY WORK;
198 USE WORK.MTI_PKG.ALL;
199 use std.textio.all;
200
201 library grlib;
202 use grlib.stdlib.all;
203 use grlib.stdio.all;
204
205 ENTITY mt48lc16m16a2 IS
206 GENERIC (
207 -- Timing Parameters for -75 (PC133) and CAS Latency = 2
208 tAC : TIME := 6.0 ns;
209 tHZ : TIME := 7.0 ns;
210 tOH : TIME := 2.7 ns;
211 tMRD : INTEGER := 2; -- 2 Clk Cycles
212 tRAS : TIME := 44.0 ns;
213 tRC : TIME := 66.0 ns;
214 tRCD : TIME := 20.0 ns;
215 tRP : TIME := 20.0 ns;
216 tRRD : TIME := 15.0 ns;
217 tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
218 tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns)
219
220 tAH : TIME := 0.8 ns;
221 tAS : TIME := 1.5 ns;
222 tCH : TIME := 2.5 ns;
223 tCL : TIME := 2.5 ns;
224 tCK : TIME := 10.0 ns;
225 tDH : TIME := 0.8 ns;
226 tDS : TIME := 1.5 ns;
227 tCKH : TIME := 0.8 ns;
228 tCKS : TIME := 1.5 ns;
229 tCMH : TIME := 0.8 ns;
230 tCMS : TIME := 1.5 ns;
231
232 addr_bits : INTEGER := 13;
233 data_bits : INTEGER := 16;
234 col_bits : INTEGER := 9;
235 index : INTEGER := 0;
236 fname : string := "ram.srec" -- File to read from
237 );
238 PORT (
239 Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
240 Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
241 Ba : IN STD_LOGIC_VECTOR := "00";
242 Clk : IN STD_LOGIC := '0';
243 Cke : IN STD_LOGIC := '1';
244 Cs_n : IN STD_LOGIC := '1';
245 Ras_n : IN STD_LOGIC := '1';
246 Cas_n : IN STD_LOGIC := '1';
247 We_n : IN STD_LOGIC := '1';
248 Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"
249 );
250 END mt48lc16m16a2;
251
252 ARCHITECTURE behave OF mt48lc16m16a2 IS
253 TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, LOAD_FILE, DUMP_FILE);
254 TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER;
255 TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME;
256 TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT;
257 TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0);
258 TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0);
259 TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State;
260 SIGNAL Operation : State := NOP;
261 SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
262 SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0';
263 SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0';
264 SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0';
265 SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0';
266 SIGNAL Ras_in, Cas_in, We_in : BIT := '0';
267 SIGNAL Write_burst_mode : BIT := '0';
268 SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0';
269
270 -- Checking internal wires
271 SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000";
272 SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000";
273 SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0';
274 SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00";
275 SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
276 SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
277
278 BEGIN
279 -- CS# Decode
280 WITH Cs_n SELECT
281 Cas_in <= TO_BIT (Cas_n, '1') WHEN '0',
282 '1' WHEN '1',
283 '1' WHEN OTHERS;
284 WITH Cs_n SELECT
285 Ras_in <= TO_BIT (Ras_n, '1') WHEN '0',
286 '1' WHEN '1',
287 '1' WHEN OTHERS;
288 WITH Cs_n SELECT
289 We_in <= TO_BIT (We_n, '1') WHEN '0',
290 '1' WHEN '1',
291 '1' WHEN OTHERS;
292
293 -- Commands Decode
294 Active_enable <= NOT(Ras_in) AND Cas_in AND We_in;
295 Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in;
296 Burst_term <= Ras_in AND Cas_in AND NOT(We_in);
297 Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in);
298 Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in);
299 Read_enable <= Ras_in AND NOT(Cas_in) AND We_in;
300 Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in);
301
302 -- Burst Length Decode
303 Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0));
304 Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0);
305 Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0));
306 Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
307
308 -- CAS Latency Decode
309 Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4));
310 Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4);
311
312 -- Write Burst Mode
313 Write_burst_mode <= Mode_reg(9);
314
315 -- RAS Clock for checking tWR and tRP
316 PROCESS
317 variable Clk0, Clk1 : integer := 0;
318 begin
319 RAS_clk <= '1';
320 wait for 0.5 ns;
321 RAS_clk <= '0';
322 wait for 0.5 ns;
323 if Clk0 > 100 or Clk1 > 100 then
324 wait;
325 else
326 if Clk = '1' and Cke = '1' then
327 Clk0 := 0;
328 Clk1 := Clk1 + 1;
329 elsif Clk = '0' and Cke = '1' then
330 Clk0 := Clk0 + 1;
331 Clk1 := 0;
332 end if;
333 end if;
334 END PROCESS;
335
336 -- System Clock
337 int_clk : PROCESS (Clk)
338 begin
339 IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN --'
340 CkeZ <= TO_BIT(Cke, '1');
341 END IF;
342 Sys_clk <= CkeZ AND TO_BIT(Clk, '0');
343 END PROCESS;
344
345 state_register : PROCESS
346 -- NOTE: The extra bits in RAM_TYPE is for checking memory access. A logic 1 means
347 -- the location is in use. This will be checked when doing memory DUMP.
348 TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits DOWNTO 0);
349 TYPE ram_pntr IS ACCESS ram_type;
350 TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr;
351 VARIABLE Bank0 : ram_stor;
352 VARIABLE Bank1 : ram_stor;
353 VARIABLE Bank2 : ram_stor;
354 VARIABLE Bank3 : ram_stor;
355 VARIABLE Row_index, Col_index : INTEGER := 0;
356 VARIABLE Dq_temp : BIT_VECTOR (data_bits DOWNTO 0) := (OTHERS => '0');
357
358 VARIABLE Col_addr : Array4xCBV;
359 VARIABLE Bank_addr : Array4x2BV;
360 VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00";
361
362 VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00";
363 VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
364 VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
365 VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
366 VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
367 VARIABLE Burst_counter : INTEGER := 0;
368
369 VARIABLE Command : Array_state;
370 VARIABLE Bank_precharge : Array4x2BV;
371 VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0');
372 VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0');
373 VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0');
374 VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0');
375 VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0');
376 VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0');
377 VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00";
378 VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
379 VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0);
380
381 VARIABLE Data_in_enable, Data_out_enable : BIT := '0';
382 VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0';
383 VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0';
384
385 -- Timing Check
386 VARIABLE MRD_chk : INTEGER := 0;
387 VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0);
388 VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
389 VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
390 VARIABLE RC_chk, RRD_chk : TIME := 0 ns;
391 VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns;
392 VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns;
393 VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns;
394
395 -- Load and Dumb variables
396 FILE file_load : TEXT open read_mode is fname; -- Data load
397 FILE file_dump : TEXT open write_mode is "dumpdata.txt"; -- Data dump
398 VARIABLE bank_load : bit_vector ( 1 DOWNTO 0);
399 VARIABLE rows_load : BIT_VECTOR (12 DOWNTO 0);
400 VARIABLE cols_load : BIT_VECTOR ( 8 DOWNTO 0);
401 VARIABLE data_load : BIT_VECTOR (15 DOWNTO 0);
402 VARIABLE i, j : INTEGER;
403 VARIABLE good_load : BOOLEAN;
404 VARIABLE l : LINE;
405 variable load : std_logic := '1';
406 variable dump : std_logic := '0';
407 variable ch : character;
408 variable rectype : bit_vector(3 downto 0);
409 variable recaddr : bit_vector(31 downto 0);
410 variable reclen : bit_vector(7 downto 0);
411 variable recdata : bit_vector(0 to 16*8-1);
412
413 -- Initialize empty rows
414 PROCEDURE Init_mem (Bank : bit_vector (1 DOWNTO 0); Row_index : INTEGER) IS
415 VARIABLE i, j : INTEGER := 0;
416 BEGIN
417 IF Bank = "00" THEN
418 IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty
419 Bank0 (Row_index) := NEW ram_type; -- Open new row for access
420 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros
421 FOR j IN (data_bits) DOWNTO 0 LOOP
422 Bank0 (Row_index) (i) (j) := '0';
423 END LOOP;
424 END LOOP;
425 END IF;
426 ELSIF Bank = "01" THEN
427 IF Bank1 (Row_index) = NULL THEN
428 Bank1 (Row_index) := NEW ram_type;
429 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
430 FOR j IN (data_bits) DOWNTO 0 LOOP
431 Bank1 (Row_index) (i) (j) := '0';
432 END LOOP;
433 END LOOP;
434 END IF;
435 ELSIF Bank = "10" THEN
436 IF Bank2 (Row_index) = NULL THEN
437 Bank2 (Row_index) := NEW ram_type;
438 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
439 FOR j IN (data_bits) DOWNTO 0 LOOP
440 Bank2 (Row_index) (i) (j) := '0';
441 END LOOP;
442 END LOOP;
443 END IF;
444 ELSIF Bank = "11" THEN
445 IF Bank3 (Row_index) = NULL THEN
446 Bank3 (Row_index) := NEW ram_type;
447 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
448 FOR j IN (data_bits) DOWNTO 0 LOOP
449 Bank3 (Row_index) (i) (j) := '0';
450 END LOOP;
451 END LOOP;
452 END IF;
453 END IF;
454 END;
455
456 -- Burst Counter
457 PROCEDURE Burst_decode IS
458 VARIABLE Col_int : INTEGER := 0;
459 VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
460 BEGIN
461 -- Advance Burst Counter
462 Burst_counter := Burst_counter + 1;
463
464 -- Burst Type
465 IF Mode_reg (3) = '0' THEN
466 Col_int := TO_INTEGER(Col);
467 Col_int := Col_int + 1;
468 TO_BITVECTOR (Col_int, Col_temp);
469 ELSIF Mode_reg (3) = '1' THEN
470 TO_BITVECTOR (Burst_counter, Col_vec);
471 Col_temp (2) := Col_vec (2) XOR Col_brst (2);
472 Col_temp (1) := Col_vec (1) XOR Col_brst (1);
473 Col_temp (0) := Col_vec (0) XOR Col_brst (0);
474 END IF;
475
476 -- Burst Length
477 IF Burst_length_2 = '1' THEN
478 Col (0) := Col_temp (0);
479 ELSIF Burst_length_4 = '1' THEN
480 Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0);
481 ELSIF Burst_length_8 = '1' THEN
482 Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0);
483 ELSE
484 Col := Col_temp;
485 END IF;
486
487 -- Burst Read Single Write
488 IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN
489 Data_in_enable := '0';
490 END IF;
491
492 -- Data counter
493 IF Burst_length_1 = '1' THEN
494 IF Burst_counter >= 1 THEN
495 IF Data_in_enable = '1' THEN
496 Data_in_enable := '0';
497 ELSIF Data_out_enable = '1' THEN
498 Data_out_enable := '0';
499 END IF;
500 END IF;
501 ELSIF Burst_length_2 = '1' THEN
502 IF Burst_counter >= 2 THEN
503 IF Data_in_enable = '1' THEN
504 Data_in_enable := '0';
505 ELSIF Data_out_enable = '1' THEN
506 Data_out_enable := '0';
507 END IF;
508 END IF;
509 ELSIF Burst_length_4 = '1' THEN
510 IF Burst_counter >= 4 THEN
511 IF Data_in_enable = '1' THEN
512 Data_in_enable := '0';
513 ELSIF Data_out_enable = '1' THEN
514 Data_out_enable := '0';
515 END IF;
516 END IF;
517 ELSIF Burst_length_8 = '1' THEN
518 IF Burst_counter >= 8 THEN
519 IF Data_in_enable = '1' THEN
520 Data_in_enable := '0';
521 ELSIF Data_out_enable = '1' THEN
522 Data_out_enable := '0';
523 END IF;
524 END IF;
525 END IF;
526 END;
527
528 BEGIN
529 WAIT ON Sys_clk, RAS_clk;
530 IF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '0' THEN --'
531 -- Internal Command Pipeline
532 Command(0) := Command(1);
533 Command(1) := Command(2);
534 Command(2) := Command(3);
535 Command(3) := NOP;
536
537 Col_addr(0) := Col_addr(1);
538 Col_addr(1) := Col_addr(2);
539 Col_addr(2) := Col_addr(3);
540 Col_addr(3) := (OTHERS => '0');
541
542 Bank_addr(0) := Bank_addr(1);
543 Bank_addr(1) := Bank_addr(2);
544 Bank_addr(2) := Bank_addr(3);
545 Bank_addr(3) := "00";
546
547 Bank_precharge(0) := Bank_precharge(1);
548 Bank_precharge(1) := Bank_precharge(2);
549 Bank_precharge(2) := Bank_precharge(3);
550 Bank_precharge(3) := "00";
551
552 A10_precharge(0) := A10_precharge(1);
553 A10_precharge(1) := A10_precharge(2);
554 A10_precharge(2) := A10_precharge(3);
555 A10_precharge(3) := '0';
556
557 -- Operation Decode (Optional for showing current command on posedge clock / debug feature)
558 IF Active_enable = '1' THEN
559 Operation <= ACT;
560 ELSIF Aref_enable = '1' THEN
561 Operation <= A_REF;
562 ELSIF Burst_term = '1' THEN
563 Operation <= BST;
564 ELSIF Mode_reg_enable = '1' THEN
565 Operation <= LMR;
566 ELSIF Prech_enable = '1' THEN
567 Operation <= PRECH;
568 ELSIF Read_enable = '1' THEN
569 IF Addr(10) = '0' THEN
570 Operation <= READ;
571 ELSE
572 Operation <= READ_A;
573 END IF;
574 ELSIF Write_enable = '1' THEN
575 IF Addr(10) = '0' THEN
576 Operation <= WRITE;
577 ELSE
578 Operation <= WRITE_A;
579 END IF;
580 ELSE
581 Operation <= NOP;
582 END IF;
583
584 -- Dqm pipeline for Read
585 Dqm_reg0 := Dqm_reg1;
586 Dqm_reg1 := TO_BITVECTOR(Dqm);
587
588 -- Read or Write with Auto Precharge Counter
589 IF Auto_precharge (0) = '1' THEN
590 Count_precharge (0) := Count_precharge (0) + 1;
591 END IF;
592 IF Auto_precharge (1) = '1' THEN
593 Count_precharge (1) := Count_precharge (1) + 1;
594 END IF;
595 IF Auto_precharge (2) = '1' THEN
596 Count_precharge (2) := Count_precharge (2) + 1;
597 END IF;
598 IF Auto_precharge (3) = '1' THEN
599 Count_precharge (3) := Count_precharge (3) + 1;
600 END IF;
601
602 -- Auto Precharge Timer for tWR
603 if (Burst_length_1 = '1' OR Write_burst_mode = '1') then
604 if (Count_precharge(0) = 1) then
605 Count_time(0) := NOW;
606 end if;
607 if (Count_precharge(1) = 1) then
608 Count_time(1) := NOW;
609 end if;
610 if (Count_precharge(2) = 1) then
611 Count_time(2) := NOW;
612 end if;
613 if (Count_precharge(3) = 1) then
614 Count_time(3) := NOW;
615 end if;
616 elsif (Burst_length_2 = '1') then
617 if (Count_precharge(0) = 2) then
618 Count_time(0) := NOW;
619 end if;
620 if (Count_precharge(1) = 2) then
621 Count_time(1) := NOW;
622 end if;
623 if (Count_precharge(2) = 2) then
624 Count_time(2) := NOW;
625 end if;
626 if (Count_precharge(3) = 2) then
627 Count_time(3) := NOW;
628 end if;
629 elsif (Burst_length_4 = '1') then
630 if (Count_precharge(0) = 4) then
631 Count_time(0) := NOW;
632 end if;
633 if (Count_precharge(1) = 4) then
634 Count_time(1) := NOW;
635 end if;
636 if (Count_precharge(2) = 4) then
637 Count_time(2) := NOW;
638 end if;
639 if (Count_precharge(3) = 4) then
640 Count_time(3) := NOW;
641 end if;
642 elsif (Burst_length_8 = '1') then
643 if (Count_precharge(0) = 8) then
644 Count_time(0) := NOW;
645 end if;
646 if (Count_precharge(1) = 8) then
647 Count_time(1) := NOW;
648 end if;
649 if (Count_precharge(2) = 8) then
650 Count_time(2) := NOW;
651 end if;
652 if (Count_precharge(3) = 8) then
653 Count_time(3) := NOW;
654 end if;
655 end if;
656
657 -- tMRD Counter
658 MRD_chk := MRD_chk + 1;
659
660 -- tWR Counter
661 WR_counter(0) := WR_counter(0) + 1;
662 WR_counter(1) := WR_counter(1) + 1;
663 WR_counter(2) := WR_counter(2) + 1;
664 WR_counter(3) := WR_counter(3) + 1;
665
666
667 -- Auto Refresh
668 IF Aref_enable = '1' THEN
669 -- Auto Refresh to Auto Refresh
670 ASSERT (NOW - RC_chk >= tRC)
671 REPORT "tRC violation during Auto Refresh"
672 SEVERITY WARNING;
673 -- Precharge to Auto Refresh
674 ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP)
675 REPORT "tRP violation during Auto Refresh"
676 SEVERITY WARNING;
677 -- All banks must be idle before refresh
678 IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN
679 ASSERT (FALSE)
680 REPORT "All banks must be Precharge before Auto Refresh"
681 SEVERITY WARNING;
682 END IF;
683 -- Record current tRC time
684 RC_chk := NOW;
685 END IF;
686
687 -- Load Mode Register
688 IF Mode_reg_enable = '1' THEN
689 Mode_reg <= TO_BITVECTOR (Addr);
690 IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN
691 ASSERT (FALSE)
692 REPORT "All bank must be Precharge before Load Mode Register"
693 SEVERITY WARNING;
694 END IF;
695 -- REF to LMR
696 ASSERT (NOW - RC_chk >= tRC)
697 REPORT "tRC violation during Load Mode Register"
698 SEVERITY WARNING;
699 -- LMR to LMR
700 ASSERT (MRD_chk >= tMRD)
701 REPORT "tMRD violation during Load Mode Register"
702 SEVERITY WARNING;
703 -- Record current tMRD time
704 MRD_chk := 0;
705 END IF;
706
707 -- Active Block (latch Bank and Row Address)
708 IF Active_enable = '1' THEN
709 IF Ba = "00" AND Pc_b0 = '1' THEN
710 Act_b0 := '1';
711 Pc_b0 := '0';
712 B0_row_addr := TO_BITVECTOR (Addr);
713 RCD_chk0 := NOW;
714 RAS_chk0 := NOW;
715 -- Precharge to Active Bank 0
716 ASSERT (NOW - RP_chk0 >= tRP)
717 REPORT "tRP violation during Activate Bank 0"
718 SEVERITY WARNING;
719 ELSIF Ba = "01" AND Pc_b1 = '1' THEN
720 Act_b1 := '1';
721 Pc_b1 := '0';
722 B1_row_addr := TO_BITVECTOR (Addr);
723 RCD_chk1 := NOW;
724 RAS_chk1 := NOW;
725 -- Precharge to Active Bank 1
726 ASSERT (NOW - RP_chk1 >= tRP)
727 REPORT "tRP violation during Activate Bank 1"
728 SEVERITY WARNING;
729 ELSIF Ba = "10" AND Pc_b2 = '1' THEN
730 Act_b2 := '1';
731 Pc_b2 := '0';
732 B2_row_addr := TO_BITVECTOR (Addr);
733 RCD_chk2 := NOW;
734 RAS_chk2 := NOW;
735 -- Precharge to Active Bank 2
736 ASSERT (NOW - RP_chk2 >= tRP)
737 REPORT "tRP violation during Activate Bank 2"
738 SEVERITY WARNING;
739 ELSIF Ba = "11" AND Pc_b3 = '1' THEN
740 Act_b3 := '1';
741 Pc_b3 := '0';
742 B3_row_addr := TO_BITVECTOR (Addr);
743 RCD_chk3 := NOW;
744 RAS_chk3 := NOW;
745 -- Precharge to Active Bank 3
746 ASSERT (NOW - RP_chk3 >= tRP)
747 REPORT "tRP violation during Activate Bank 3"
748 SEVERITY WARNING;
749 ELSIF Ba = "00" AND Pc_b0 = '0' THEN
750 ASSERT (FALSE)
751 REPORT "Bank 0 is not Precharged"
752 SEVERITY WARNING;
753 ELSIF Ba = "01" AND Pc_b1 = '0' THEN
754 ASSERT (FALSE)
755 REPORT "Bank 1 is not Precharged"
756 SEVERITY WARNING;
757 ELSIF Ba = "10" AND Pc_b2 = '0' THEN
758 ASSERT (FALSE)
759 REPORT "Bank 2 is not Precharged"
760 SEVERITY WARNING;
761 ELSIF Ba = "11" AND Pc_b3 = '0' THEN
762 ASSERT (FALSE)
763 REPORT "Bank 3 is not Precharged"
764 SEVERITY WARNING;
765 END IF;
766 -- Active Bank A to Active Bank B
767 IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN
768 ASSERT (FALSE)
769 REPORT "tRRD violation during Activate"
770 SEVERITY WARNING;
771 END IF;
772 -- LMR to ACT
773 ASSERT (MRD_chk >= tMRD)
774 REPORT "tMRD violation during Activate"
775 SEVERITY WARNING;
776 -- AutoRefresh to Activate
777 ASSERT (NOW - RC_chk >= tRC)
778 REPORT "tRC violation during Activate"
779 SEVERITY WARNING;
780 -- Record variable for checking violation
781 RRD_chk := NOW;
782 Previous_bank := TO_BITVECTOR (Ba);
783 END IF;
784
785 -- Precharge Block
786 IF Prech_enable = '1' THEN
787 IF Addr(10) = '1' THEN
788 Pc_b0 := '1';
789 Pc_b1 := '1';
790 Pc_b2 := '1';
791 Pc_b3 := '1';
792 Act_b0 := '0';
793 Act_b1 := '0';
794 Act_b2 := '0';
795 Act_b3 := '0';
796 RP_chk0 := NOW;
797 RP_chk1 := NOW;
798 RP_chk2 := NOW;
799 RP_chk3 := NOW;
800 -- Activate to Precharge all banks
801 ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS))
802 REPORT "tRAS violation during Precharge all banks"
803 SEVERITY WARNING;
804 -- tWR violation check for Write
805 IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR
806 (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN
807 ASSERT (FALSE)
808 REPORT "tWR violation during Precharge ALL banks"
809 SEVERITY WARNING;
810 END IF;
811 ELSIF Addr(10) = '0' THEN
812 IF Ba = "00" THEN
813 Pc_b0 := '1';
814 Act_b0 := '0';
815 RP_chk0 := NOW;
816 -- Activate to Precharge bank 0
817 ASSERT (NOW - RAS_chk0 >= tRAS)
818 REPORT "tRAS violation during Precharge bank 0"
819 SEVERITY WARNING;
820 ELSIF Ba = "01" THEN
821 Pc_b1 := '1';
822 Act_b1 := '0';
823 RP_chk1 := NOW;
824 -- Activate to Precharge bank 1
825 ASSERT (NOW - RAS_chk1 >= tRAS)
826 REPORT "tRAS violation during Precharge bank 1"
827 SEVERITY WARNING;
828 ELSIF Ba = "10" THEN
829 Pc_b2 := '1';
830 Act_b2 := '0';
831 RP_chk2 := NOW;
832 -- Activate to Precharge bank 2
833 ASSERT (NOW - RAS_chk2 >= tRAS)
834 REPORT "tRAS violation during Precharge bank 2"
835 SEVERITY WARNING;
836 ELSIF Ba = "11" THEN
837 Pc_b3 := '1';
838 Act_b3 := '0';
839 RP_chk3 := NOW;
840 -- Activate to Precharge bank 3
841 ASSERT (NOW - RAS_chk3 >= tRAS)
842 REPORT "tRAS violation during Precharge bank 3"
843 SEVERITY WARNING;
844 END IF;
845 -- tWR violation check for Write
846 ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp)
847 REPORT "tWR violation during Precharge"
848 SEVERITY WARNING;
849 END IF;
850 -- Terminate a Write Immediately (if same bank or all banks)
851 IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN
852 Data_in_enable := '0';
853 END IF;
854 -- Precharge Command Pipeline for READ
855 IF CAS_latency_3 = '1' THEN
856 Command(2) := PRECH;
857 Bank_precharge(2) := TO_BITVECTOR (Ba);
858 A10_precharge(2) := TO_BIT(Addr(10));
859 ELSIF CAS_latency_2 = '1' THEN
860 Command(1) := PRECH;
861 Bank_precharge(1) := TO_BITVECTOR (Ba);
862 A10_precharge(1) := TO_BIT(Addr(10));
863 END IF;
864 END IF;
865
866 -- Burst Terminate
867 IF Burst_term = '1' THEN
868 -- Terminate a Write immediately
869 IF Data_in_enable = '1' THEN
870 Data_in_enable := '0';
871 END IF;
872 -- Terminate a Read depend on CAS Latency
873 IF CAS_latency_3 = '1' THEN
874 Command(2) := BST;
875 ELSIF CAS_latency_2 = '1' THEN
876 Command(1) := BST;
877 END IF;
878 END IF;
879
880 -- Read, Write, Column Latch
881 IF Read_enable = '1' OR Write_enable = '1' THEN
882 -- Check to see if bank is open (ACT) for Read or Write
883 IF ((Ba="00" AND Pc_b0='1') OR (Ba="01" AND Pc_b1='1') OR (Ba="10" AND Pc_b2='1') OR (Ba="11" AND Pc_b3='1')) THEN
884 ASSERT (FALSE)
885 REPORT "Cannot Read or Write - Bank is not Activated"
886 SEVERITY WARNING;
887 END IF;
888 -- Activate to Read or Write
889 IF Ba = "00" THEN
890 ASSERT (NOW - RCD_chk0 >= tRCD)
891 REPORT "tRCD violation during Read or Write to Bank 0"
892 SEVERITY WARNING;
893 ELSIF Ba = "01" THEN
894 ASSERT (NOW - RCD_chk1 >= tRCD)
895 REPORT "tRCD violation during Read or Write to Bank 1"
896 SEVERITY WARNING;
897 ELSIF Ba = "10" THEN
898 ASSERT (NOW - RCD_chk2 >= tRCD)
899 REPORT "tRCD violation during Read or Write to Bank 2"
900 SEVERITY WARNING;
901 ELSIF Ba = "11" THEN
902 ASSERT (NOW - RCD_chk3 >= tRCD)
903 REPORT "tRCD violation during Read or Write to Bank 3"
904 SEVERITY WARNING;
905 END IF;
906
907 -- Read Command
908 IF Read_enable = '1' THEN
909 -- CAS Latency Pipeline
910 IF Cas_latency_3 = '1' THEN
911 IF Addr(10) = '1' THEN
912 Command(2) := READ_A;
913 ELSE
914 Command(2) := READ;
915 END IF;
916 Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
917 Bank_addr (2) := TO_BITVECTOR (Ba);
918 ELSIF Cas_latency_2 = '1' THEN
919 IF Addr(10) = '1' THEN
920 Command(1) := READ_A;
921 ELSE
922 Command(1) := READ;
923 END IF;
924 Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
925 Bank_addr (1) := TO_BITVECTOR (Ba);
926 END IF;
927
928 -- Read intterupt a Write (terminate Write immediately)
929 IF Data_in_enable = '1' THEN
930 Data_in_enable := '0';
931 END IF;
932
933 -- Write Command
934 ELSIF Write_enable = '1' THEN
935 IF Addr(10) = '1' THEN
936 Command(0) := WRITE_A;
937 ELSE
938 Command(0) := WRITE;
939 END IF;
940 Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
941 Bank_addr (0) := TO_BITVECTOR (Ba);
942
943 -- Write intterupt a Write (terminate Write immediately)
944 IF Data_in_enable = '1' THEN
945 Data_in_enable := '0';
946 END IF;
947
948 -- Write interrupt a Read (terminate Read immediately)
949 IF Data_out_enable = '1' THEN
950 Data_out_enable := '0';
951 END IF;
952 END IF;
953
954 -- Interrupt a Write with Auto Precharge
955 IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Write_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN
956 RW_interrupt_write(TO_INTEGER(RW_Interrupt_Bank)) := '1';
957 END IF;
958
959 -- Interrupt a Read with Auto Precharge
960 IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Read_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN
961 RW_interrupt_read(TO_INTEGER(RW_Interrupt_Bank)) := '1';
962 END IF;
963
964 -- Read or Write with Auto Precharge
965 IF Addr(10) = '1' THEN
966 Auto_precharge (TO_INTEGER(Ba)) := '1';
967 Count_precharge (TO_INTEGER(Ba)) := 0;
968 RW_Interrupt_Bank := TO_BitVector(Ba);
969 IF Read_enable = '1' THEN
970 Read_precharge (TO_INTEGER(Ba)) := '1';
971 ELSIF Write_enable = '1' THEN
972 Write_precharge (TO_INTEGER(Ba)) := '1';
973 END IF;
974 END IF;
975 END IF;
976
977 -- Read with AutoPrecharge Calculation
978 -- The device start internal precharge when:
979 -- 1. BL/2 cycles after command
980 -- and 2. Meet tRAS requirement
981 -- or 3. Interrupt by a Read or Write (with or without Auto Precharge)
982 IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN
983 IF (((NOW - RAS_chk0 >= tRAS) AND
984 ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR
985 (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR
986 (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR
987 (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR
988 (RW_interrupt_read(0) = '1')) THEN
989 Pc_b0 := '1';
990 Act_b0 := '0';
991 RP_chk0 := NOW;
992 Auto_precharge(0) := '0';
993 Read_precharge(0) := '0';
994 RW_interrupt_read(0) := '0';
995 END IF;
996 END IF;
997 IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN
998 IF (((NOW - RAS_chk1 >= tRAS) AND
999 ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR
1000 (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR
1001 (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR
1002 (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR
1003 (RW_interrupt_read(1) = '1')) THEN
1004 Pc_b1 := '1';
1005 Act_b1 := '0';
1006 RP_chk1 := NOW;
1007 Auto_precharge(1) := '0';
1008 Read_precharge(1) := '0';
1009 RW_interrupt_read(1) := '0';
1010 END IF;
1011 END IF;
1012 IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN
1013 IF (((NOW - RAS_chk2 >= tRAS) AND
1014 ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR
1015 (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR
1016 (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR
1017 (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR
1018 (RW_interrupt_read(2) = '1')) THEN
1019 Pc_b2 := '1';
1020 Act_b2 := '0';
1021 RP_chk2 := NOW;
1022 Auto_precharge(2) := '0';
1023 Read_precharge(2) := '0';
1024 RW_interrupt_read(2) := '0';
1025 END IF;
1026 END IF;
1027 IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN
1028 IF (((NOW - RAS_chk3 >= tRAS) AND
1029 ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR
1030 (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR
1031 (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR
1032 (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR
1033 (RW_interrupt_read(3) = '1')) THEN
1034 Pc_b3 := '1';
1035 Act_b3 := '0';
1036 RP_chk3 := NOW;
1037 Auto_precharge(3) := '0';
1038 Read_precharge(3) := '0';
1039 RW_interrupt_read(3) := '0';
1040 END IF;
1041 END IF;
1042
1043 -- Internal Precharge or Bst
1044 IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks
1045 IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN
1046 IF Data_out_enable = '1' THEN
1047 Data_out_enable := '0';
1048 END IF;
1049 END IF;
1050 ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank
1051 IF Data_out_enable = '1' THEN
1052 Data_out_enable := '0';
1053 END IF;
1054 END IF;
1055
1056 IF Data_out_enable = '0' THEN
1057 Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH;
1058 END IF;
1059
1060 -- Detect Read or Write Command
1061 IF Command(0) = READ OR Command(0) = READ_A THEN
1062 Bank := Bank_addr (0);
1063 Col := Col_addr (0);
1064 Col_brst := Col_addr (0);
1065 IF Bank_addr (0) = "00" THEN
1066 Row := B0_row_addr;
1067 ELSIF Bank_addr (0) = "01" THEN
1068 Row := B1_row_addr;
1069 ELSIF Bank_addr (0) = "10" THEN
1070 Row := B2_row_addr;
1071 ELSE
1072 Row := B3_row_addr;
1073 END IF;
1074 Burst_counter := 0;
1075 Data_in_enable := '0';
1076 Data_out_enable := '1';
1077 ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN
1078 Bank := Bank_addr(0);
1079 Col := Col_addr(0);
1080 Col_brst := Col_addr(0);
1081 IF Bank_addr (0) = "00" THEN
1082 Row := B0_row_addr;
1083 ELSIF Bank_addr (0) = "01" THEN
1084 Row := B1_row_addr;
1085 ELSIF Bank_addr (0) = "10" THEN
1086 Row := B2_row_addr;
1087 ELSE
1088 Row := B3_row_addr;
1089 END IF;
1090 Burst_counter := 0;
1091 Data_in_enable := '1';
1092 Data_out_enable := '0';
1093 END IF;
1094
1095 -- DQ (Driver / Receiver)
1096 Row_index := TO_INTEGER (Row);
1097 Col_index := TO_INTEGER (Col);
1098 IF Data_in_enable = '1' THEN
1099 IF Dqm /= "11" THEN
1100 Init_mem (Bank, Row_index);
1101 IF Bank = "00" THEN
1102 Dq_temp := Bank0 (Row_index) (Col_index);
1103 IF Dqm = "01" THEN
1104 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1105 ELSIF Dqm = "10" THEN
1106 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1107 ELSE
1108 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1109 END IF;
1110 Bank0 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1111 ELSIF Bank = "01" THEN
1112 Dq_temp := Bank1 (Row_index) (Col_index);
1113 IF Dqm = "01" THEN
1114 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1115 ELSIF Dqm = "10" THEN
1116 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1117 ELSE
1118 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1119 END IF;
1120 Bank1 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1121 ELSIF Bank = "10" THEN
1122 Dq_temp := Bank2 (Row_index) (Col_index);
1123 IF Dqm = "01" THEN
1124 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1125 ELSIF Dqm = "10" THEN
1126 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1127 ELSE
1128 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1129 END IF;
1130 Bank2 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1131 ELSIF Bank = "11" THEN
1132 Dq_temp := Bank3 (Row_index) (Col_index);
1133 IF Dqm = "01" THEN
1134 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1135 ELSIF Dqm = "10" THEN
1136 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1137 ELSE
1138 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1139 END IF;
1140 Bank3 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1141 END IF;
1142 WR_chkp(TO_INTEGER(Bank)) := NOW;
1143 WR_counter(TO_INTEGER(Bank)) := 0;
1144 END IF;
1145 Burst_decode;
1146 ELSIF Data_out_enable = '1' THEN
1147 IF Dqm_reg0 /= "11" THEN
1148 Init_mem (Bank, Row_index);
1149 IF Bank = "00" THEN
1150 Dq_temp := Bank0 (Row_index) (Col_index);
1151 IF Dqm_reg0 = "00" THEN
1152 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1153 ELSIF Dqm_reg0 = "01" THEN
1154 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1155 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1156 ELSIF Dqm_reg0 = "10" THEN
1157 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1158 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1159 END IF;
1160 ELSIF Bank = "01" THEN
1161 Dq_temp := Bank1 (Row_index) (Col_index);
1162 IF Dqm_reg0 = "00" THEN
1163 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1164 ELSIF Dqm_reg0 = "01" THEN
1165 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1166 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1167 ELSIF Dqm_reg0 = "10" THEN
1168 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1169 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1170 END IF;
1171 ELSIF Bank = "10" THEN
1172 Dq_temp := Bank2 (Row_index) (Col_index);
1173 IF Dqm_reg0 = "00" THEN
1174 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1175 ELSIF Dqm_reg0 = "01" THEN
1176 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1177 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1178 ELSIF Dqm_reg0 = "10" THEN
1179 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1180 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1181 END IF;
1182 ELSIF Bank = "11" THEN
1183 Dq_temp := Bank3 (Row_index) (Col_index);
1184 IF Dqm_reg0 = "00" THEN
1185 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1186 ELSIF Dqm_reg0 = "01" THEN
1187 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1188 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1189 ELSIF Dqm_reg0 = "10" THEN
1190 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1191 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1192 END IF;
1193 END IF;
1194 ELSE
1195 Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ;
1196 END IF;
1197 Burst_decode;
1198 END IF;
1199 ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '1' AND Dump = '0' THEN --'
1200 Operation <= LOAD_FILE;
1201 load := '0';
1202 -- ASSERT (FALSE) REPORT "Reading memory array from file. This operation may take several minutes. Please wait..."
1203 -- SEVERITY NOTE;
1204 WHILE NOT endfile(file_load) LOOP
1205 readline(file_load, l);
1206 read(l, ch);
1207 if (ch /= 'S') or (ch /= 's') then
1208 hread(l, rectype);
1209 hread(l, reclen);
1210 recaddr := (others => '0');
1211 case rectype is
1212 when "0001" =>
1213 hread(l, recaddr(15 downto 0));
1214 when "0010" =>
1215 hread(l, recaddr(23 downto 0));
1216 when "0011" =>
1217 hread(l, recaddr);
1218 recaddr(31 downto 24) := (others => '0');
1219 when others => next;
1220 end case;
1221 hread(l, recdata);
1222
1223 if index < 32 then
1224 Bank_Load := recaddr(25 downto 24);
1225 Rows_Load := recaddr(23 downto 11);
1226 Cols_Load := recaddr(10 downto 2);
1227 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1228 IF Bank_Load = "00" THEN
1229 for i in 0 to 3 loop
1230 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1231 end loop;
1232 ELSIF Bank_Load = "01" THEN
1233 for i in 0 to 3 loop
1234 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1235 end loop;
1236 ELSIF Bank_Load = "10" THEN
1237 for i in 0 to 3 loop
1238 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1239 end loop;
1240 ELSIF Bank_Load = "11" THEN
1241 for i in 0 to 3 loop
1242 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1243 end loop;
1244 END IF;
1245 elsif(index < 1024) then
1246 Bank_Load := recaddr(26 downto 25);
1247 Rows_Load := recaddr(24 downto 12);
1248 Cols_Load := recaddr(11 downto 3);
1249 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1250 IF Bank_Load = "00" THEN
1251 for i in 0 to 1 loop
1252 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1253 end loop;
1254 ELSIF Bank_Load = "01" THEN
1255 for i in 0 to 1 loop
1256 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1257 end loop;
1258 ELSIF Bank_Load = "10" THEN
1259 for i in 0 to 1 loop
1260 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1261 end loop;
1262 ELSIF Bank_Load = "11" THEN
1263 for i in 0 to 1 loop
1264 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1265 end loop;
1266 END IF;
1267 else
1268 Bank_Load := recaddr(22 downto 21);
1269 Rows_Load := '0' & recaddr(20 downto 9);
1270 Cols_Load := '0' & recaddr(8 downto 1);
1271 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1272 IF Bank_Load = "00" THEN
1273 for i in 0 to 7 loop
1274 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1275 end loop;
1276 ELSIF Bank_Load = "01" THEN
1277 for i in 0 to 7 loop
1278 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1279 end loop;
1280 ELSIF Bank_Load = "10" THEN
1281 for i in 0 to 7 loop
1282 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1283 end loop;
1284 ELSIF Bank_Load = "11" THEN
1285 for i in 0 to 7 loop
1286 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1287 end loop;
1288 END IF;
1289 END IF;
1290 END IF;
1291 END LOOP;
1292 ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '1' THEN --'
1293 Operation <= DUMP_FILE;
1294 ASSERT (FALSE) REPORT "Writing memory array to file. This operation may take several minutes. Please wait..."
1295 SEVERITY NOTE;
1296 WRITE (l, string'("# Micron Technology, Inc. (FILE DUMP / MEMORY DUMP)")); --'
1297 WRITELINE (file_dump, l);
1298 WRITE (l, string'("# BA ROWS COLS DQ")); --'
1299 WRITELINE (file_dump, l);
1300 WRITE (l, string'("# -- ------------- --------- ----------------")); --'
1301 WRITELINE (file_dump, l);
1302 -- Dumping Bank 0
1303 FOR i IN 0 TO 2**addr_bits -1 LOOP
1304 -- Check if ROW is NULL
1305 IF Bank0 (i) /= NULL THEN
1306 For j IN 0 TO 2**col_bits - 1 LOOP
1307 -- Check if COL is NULL
1308 NEXT WHEN Bank0 (i) (j) (data_bits) = '0';
1309 WRITE (l, string'("00"), right, 4); --'
1310 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1311 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1312 WRITE (l, Bank0 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1313 WRITELINE (file_dump, l);
1314 END LOOP;
1315 END IF;
1316 END LOOP;
1317 -- Dumping Bank 1
1318 FOR i IN 0 TO 2**addr_bits -1 LOOP
1319 -- Check if ROW is NULL
1320 IF Bank1 (i) /= NULL THEN
1321 For j IN 0 TO 2**col_bits - 1 LOOP
1322 -- Check if COL is NULL
1323 NEXT WHEN Bank1 (i) (j) (data_bits) = '0';
1324 WRITE (l, string'("01"), right, 4); --'
1325 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1326 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1327 WRITE (l, Bank1 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1328 WRITELINE (file_dump, l);
1329 END LOOP;
1330 END IF;
1331 END LOOP;
1332 -- Dumping Bank 2
1333 FOR i IN 0 TO 2**addr_bits -1 LOOP
1334 -- Check if ROW is NULL
1335 IF Bank2 (i) /= NULL THEN
1336 For j IN 0 TO 2**col_bits - 1 LOOP
1337 -- Check if COL is NULL
1338 NEXT WHEN Bank2 (i) (j) (data_bits) = '0';
1339 WRITE (l, string'("10"), right, 4); --'
1340 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1341 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1342 WRITE (l, Bank2 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1343 WRITELINE (file_dump, l);
1344 END LOOP;
1345 END IF;
1346 END LOOP;
1347 -- Dumping Bank 3
1348 FOR i IN 0 TO 2**addr_bits -1 LOOP
1349 -- Check if ROW is NULL
1350 IF Bank3 (i) /= NULL THEN
1351 For j IN 0 TO 2**col_bits - 1 LOOP
1352 -- Check if COL is NULL
1353 NEXT WHEN Bank3 (i) (j) (data_bits) = '0';
1354 WRITE (l, string'("11"), right, 4); --'
1355 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1356 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1357 WRITE (l, Bank3 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1358 WRITELINE (file_dump, l);
1359 END LOOP;
1360 END IF;
1361 END LOOP;
1362 END IF;
1363
1364 -- Write with AutoPrecharge Calculation
1365 -- The device start internal precharge when:
1366 -- 1. tWR cycles after command
1367 -- and 2. Meet tRAS requirement
1368 -- or 3. Interrupt by a Read or Write (with or without Auto Precharge)
1369 IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN
1370 IF (((NOW - RAS_chk0 >= tRAS) AND
1371 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR
1372 (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR
1373 (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR
1374 (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR
1375 (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN
1376 Auto_precharge(0) := '0';
1377 Write_precharge(0) := '0';
1378 RW_interrupt_write(0) := '0';
1379 Pc_b0 := '1';
1380 Act_b0 := '0';
1381 RP_chk0 := NOW;
1382 ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE;
1383 END IF;
1384 END IF;
1385 IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN
1386 IF (((NOW - RAS_chk1 >= tRAS) AND
1387 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR
1388 (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR
1389 (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR
1390 (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR
1391 (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN
1392 Auto_precharge(1) := '0';
1393 Write_precharge(1) := '0';
1394 RW_interrupt_write(1) := '0';
1395 Pc_b1 := '1';
1396 Act_b1 := '0';
1397 RP_chk1 := NOW;
1398 END IF;
1399 END IF;
1400 IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN
1401 IF (((NOW - RAS_chk2 >= tRAS) AND
1402 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR
1403 (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR
1404 (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR
1405 (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR
1406 (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN
1407 Auto_precharge(2) := '0';
1408 Write_precharge(2) := '0';
1409 RW_interrupt_write(2) := '0';
1410 Pc_b2 := '1';
1411 Act_b2 := '0';
1412 RP_chk2 := NOW;
1413 END IF;
1414 END IF;
1415 IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN
1416 IF (((NOW - RAS_chk3 >= tRAS) AND
1417 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR
1418 (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR
1419 (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR
1420 (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR
1421 (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN
1422 Auto_precharge(3) := '0';
1423 Write_precharge(3) := '0';
1424 RW_interrupt_write(3) := '0';
1425 Pc_b3 := '1';
1426 Act_b3 := '0';
1427 RP_chk3 := NOW;
1428 END IF;
1429 END IF;
1430
1431 -- Checking internal wires (Optional for debug purpose)
1432 Pre_chk (0) <= Pc_b0;
1433 Pre_chk (1) <= Pc_b1;
1434 Pre_chk (2) <= Pc_b2;
1435 Pre_chk (3) <= Pc_b3;
1436 Act_chk (0) <= Act_b0;
1437 Act_chk (1) <= Act_b1;
1438 Act_chk (2) <= Act_b2;
1439 Act_chk (3) <= Act_b3;
1440 Dq_in_chk <= Data_in_enable;
1441 Dq_out_chk <= Data_out_enable;
1442 Bank_chk <= Bank;
1443 Row_chk <= Row;
1444 Col_chk <= Col;
1445 END PROCESS;
1446
1447
1448 -- Clock timing checks
1449 -- Clock_check : PROCESS
1450 -- VARIABLE Clk_low, Clk_high : TIME := 0 ns;
1451 -- BEGIN
1452 -- WAIT ON Clk;
1453 -- IF (Clk = '1' AND NOW >= 10 ns) THEN
1454 -- ASSERT (NOW - Clk_low >= tCL)
1455 -- REPORT "tCL violation"
1456 -- SEVERITY WARNING;
1457 -- ASSERT (NOW - Clk_high >= tCK)
1458 -- REPORT "tCK violation"
1459 -- SEVERITY WARNING;
1460 -- Clk_high := NOW;
1461 -- ELSIF (Clk = '0' AND NOW /= 0 ns) THEN
1462 -- ASSERT (NOW - Clk_high >= tCH)
1463 -- REPORT "tCH violation"
1464 -- SEVERITY WARNING;
1465 -- Clk_low := NOW;
1466 -- END IF;
1467 -- END PROCESS;
1468
1469 -- Setup timing checks
1470 Setup_check : PROCESS
1471 BEGIN
1472 wait;
1473 WAIT ON Clk;
1474 IF Clk = '1' THEN
1475 ASSERT(Cke'LAST_EVENT >= tCKS) --'
1476 REPORT "CKE Setup time violation -- tCKS"
1477 SEVERITY WARNING;
1478 ASSERT(Cs_n'LAST_EVENT >= tCMS) --'
1479 REPORT "CS# Setup time violation -- tCMS"
1480 SEVERITY WARNING;
1481 ASSERT(Cas_n'LAST_EVENT >= tCMS) --'
1482 REPORT "CAS# Setup time violation -- tCMS"
1483 SEVERITY WARNING;
1484 ASSERT(Ras_n'LAST_EVENT >= tCMS) --'
1485 REPORT "RAS# Setup time violation -- tCMS"
1486 SEVERITY WARNING;
1487 ASSERT(We_n'LAST_EVENT >= tCMS) --'
1488 REPORT "WE# Setup time violation -- tCMS"
1489 SEVERITY WARNING;
1490 ASSERT(Dqm'LAST_EVENT >= tCMS) --'
1491 REPORT "Dqm Setup time violation -- tCMS"
1492 SEVERITY WARNING;
1493 ASSERT(Addr'LAST_EVENT >= tAS) --'
1494 REPORT "ADDR Setup time violation -- tAS"
1495 SEVERITY WARNING;
1496 ASSERT(Ba'LAST_EVENT >= tAS) --'
1497 REPORT "BA Setup time violation -- tAS"
1498 SEVERITY WARNING;
1499 ASSERT(Dq'LAST_EVENT >= tDS) --'
1500 REPORT "Dq Setup time violation -- tDS"
1501 SEVERITY WARNING;
1502 END IF;
1503 END PROCESS;
1504
1505 -- Hold timing checks
1506 Hold_check : PROCESS
1507 BEGIN
1508 wait;
1509 WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH);
1510 IF Clk'DELAYED (tCKH) = '1' THEN --'
1511 ASSERT(Cke'LAST_EVENT > tCKH) --'
1512 REPORT "CKE Hold time violation -- tCKH"
1513 SEVERITY WARNING;
1514 END IF;
1515 IF Clk'DELAYED (tCMH) = '1' THEN --'
1516 ASSERT(Cs_n'LAST_EVENT > tCMH) --'
1517 REPORT "CS# Hold time violation -- tCMH"
1518 SEVERITY WARNING;
1519 ASSERT(Cas_n'LAST_EVENT > tCMH) --'
1520 REPORT "CAS# Hold time violation -- tCMH"
1521 SEVERITY WARNING;
1522 ASSERT(Ras_n'LAST_EVENT > tCMH) --'
1523 REPORT "RAS# Hold time violation -- tCMH"
1524 SEVERITY WARNING;
1525 ASSERT(We_n'LAST_EVENT > tCMH) --'
1526 REPORT "WE# Hold time violation -- tCMH"
1527 SEVERITY WARNING;
1528 ASSERT(Dqm'LAST_EVENT > tCMH) --'
1529 REPORT "Dqm Hold time violation -- tCMH"
1530 SEVERITY WARNING;
1531 END IF;
1532 IF Clk'DELAYED (tAH) = '1' THEN --'
1533 ASSERT(Addr'LAST_EVENT > tAH) --'
1534 REPORT "ADDR Hold time violation -- tAH"
1535 SEVERITY WARNING;
1536 ASSERT(Ba'LAST_EVENT > tAH) --'
1537 REPORT "BA Hold time violation -- tAH"
1538 SEVERITY WARNING;
1539 END IF;
1540 IF Clk'DELAYED (tDH) = '1' THEN --'
1541 ASSERT(Dq'LAST_EVENT > tDH) --'
1542 REPORT "Dq Hold time violation -- tDH"
1543 SEVERITY WARNING;
1544 END IF;
1545 END PROCESS;
1546
1547 END behave;
1548
1549 -- pragma translate_on
1550
This diff has been collapsed as it changes many lines, (1053 lines changed) Show them Hide them
@@ -0,0 +1,1053
1 ------------------------------------------------------------------------------
2 -- This file is a part of the GRLIB VHDL IP LIBRARY
3 -- Copyright (C) 2003 - 2008, Gaisler Research
4 -- Copyright (C) 2008 - 2014, Aeroflex Gaisler
5 -- Copyright (C) 2015 - 2016, Cobham Gaisler
6 --
7 -- This program is free software; you can redistribute it and/or modify
8 -- it under the terms of the GNU General Public License as published by
9 -- the Free Software Foundation; either version 2 of the License, or
10 -- (at your option) any later version.
11 --
12 -- This program is distributed in the hope that it will be useful,
13 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 -- GNU General Public License for more details.
16 --
17 -- You should have received a copy of the GNU General Public License
18 -- along with this program; if not, write to the Free Software
19 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 -----------------------------------------------------------------------------
21 -- Entity: sdctrl16
22 -- File: sdctrl16.vhd
23 -- Author: Jiri Gaisler - Gaisler Research
24 -- Modified by: Daniel Bengtsson & Richard Fång
25 -- Description: 16- and 32-bit SDRAM memory controller.
26 ------------------------------------------------------------------------------
27
28 library ieee;
29 use ieee.std_logic_1164.all;
30 library grlib;
31 use grlib.amba.all;
32 use grlib.stdlib.all;
33 library gaisler;
34 use grlib.devices.all;
35 use gaisler.memctrl.all;
36
37 entity sdctrl16 is
38 generic (
39 hindex : integer := 0;
40 haddr : integer := 0;
41 hmask : integer := 16#f00#;
42 ioaddr : integer := 16#000#;
43 iomask : integer := 16#fff#;
44 wprot : integer := 0;
45 invclk : integer := 0;
46 fast : integer := 0;
47 pwron : integer := 0;
48 sdbits : integer := 16;
49 oepol : integer := 0;
50 pageburst : integer := 0;
51 mobile : integer := 0
52 );
53 port (
54 rst : in std_ulogic;
55 clk : in std_ulogic;
56 ahbsi : in ahb_slv_in_type;
57 ahbso : out ahb_slv_out_type;
58 sdi : in sdctrl_in_type;
59 sdo : out sdctrl_out_type
60 );
61 end;
62
63 architecture rtl of sdctrl16 is
64
65 constant WPROTEN : boolean := wprot = 1;
66 constant SDINVCLK : boolean := invclk = 1;
67 constant BUS16 : boolean := (sdbits = 16);
68 constant BUS32 : boolean := (sdbits = 32);
69 constant BUS64 : boolean := (sdbits = 64);
70
71 constant REVISION : integer := 1;
72
73 constant PM_PD : std_logic_vector(2 downto 0) := "001";
74 constant PM_SR : std_logic_vector(2 downto 0) := "010";
75 constant PM_DPD : std_logic_vector(2 downto 0) := "101";
76
77 constant std_rammask: Std_Logic_Vector(31 downto 20) :=
78 Conv_Std_Logic_Vector(hmask, 12);
79
80 constant hconfig : ahb_config_type := (
81 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_SDCTRL, 0, REVISION, 0),
82 4 => ahb_membar(haddr, '1', '1', hmask),
83 5 => ahb_iobar(ioaddr, iomask),
84 others => zero32);
85
86 type mcycletype is (midle, active, leadout);
87 type sdcycletype is (act1, act2, act3, act3_16, rd1, rd2, rd3, rd4, rd4_16, rd5, rd6, rd7, rd8,
88 wr1, wr1_16, wr2, wr3, wr4, wr5, sidle,
89 sref, pd, dpd);
90 type icycletype is (iidle, pre, ref, lmode, emode, finish);
91
92 -- sdram configuration register
93
94 type sdram_cfg_type is record
95 command : std_logic_vector(2 downto 0);
96 csize : std_logic_vector(1 downto 0);
97 bsize : std_logic_vector(2 downto 0);
98 casdel : std_ulogic; -- CAS to data delay: 2/3 clock cycles
99 trfc : std_logic_vector(2 downto 0);
100 trp : std_ulogic; -- precharge to activate: 2/3 clock cycles
101 refresh : std_logic_vector(14 downto 0);
102 renable : std_ulogic;
103 pageburst : std_ulogic;
104 mobileen : std_logic_vector(1 downto 0); -- Mobile SD support, Mobile SD enabled
105 ds : std_logic_vector(3 downto 0); -- ds(1:0) (ds(3:2) used to detect update)
106 tcsr : std_logic_vector(3 downto 0); -- tcrs(1:0) (tcrs(3:2) used to detect update)
107 pasr : std_logic_vector(5 downto 0); -- pasr(2:0) (pasr(5:3) used to detect update)
108 pmode : std_logic_vector(2 downto 0); -- Power-Saving mode
109 txsr : std_logic_vector(3 downto 0); -- Exit Self Refresh timing
110 cke : std_ulogic; -- Clock enable
111 end record;
112
113 -- local registers
114
115 type reg_type is record
116 hready : std_ulogic;
117 hsel : std_ulogic;
118 bdrive : std_ulogic;
119 nbdrive : std_ulogic;
120 burst : std_ulogic;
121 wprothit : std_ulogic;
122 hio : std_ulogic;
123 startsd : std_ulogic;
124 lhw : std_ulogic; --Lower halfword
125
126 mstate : mcycletype;
127 sdstate : sdcycletype;
128 cmstate : mcycletype;
129 istate : icycletype;
130 icnt : std_logic_vector(2 downto 0);
131
132 haddr : std_logic_vector(31 downto 0);
133 hrdata : std_logic_vector((sdbits-1)+((16/sdbits)*16) downto 0);
134 hwdata : std_logic_vector(31 downto 0);
135 hwrite : std_ulogic;
136 htrans : std_logic_vector(1 downto 0);
137 hresp : std_logic_vector(1 downto 0);
138 size : std_logic_vector(1 downto 0);
139
140 cfg : sdram_cfg_type;
141 trfc : std_logic_vector(3 downto 0);
142 refresh : std_logic_vector(14 downto 0);
143 sdcsn : std_logic_vector(1 downto 0);
144 sdwen : std_ulogic;
145 rasn : std_ulogic;
146 casn : std_ulogic;
147 dqm : std_logic_vector(7 downto 0);
148 address : std_logic_vector(16 downto 2); -- memory address
149 bsel : std_ulogic;
150
151 idlecnt : std_logic_vector(3 downto 0); -- Counter, 16 idle clock sycles before entering Power-Saving mode
152 sref_tmpcom : std_logic_vector(2 downto 0); -- Save SD command when exit sref
153 end record;
154
155 signal r, ri : reg_type;
156 signal rbdrive, ribdrive : std_logic_vector(31 downto 0);
157 attribute syn_preserve : boolean;
158 attribute syn_preserve of rbdrive : signal is true;
159
160 begin
161
162 ctrl : process(rst, ahbsi, r, sdi, rbdrive)
163 variable v : reg_type; -- local variables for registers
164 variable startsd : std_ulogic;
165 variable dataout : std_logic_vector(31 downto 0); -- data from memory
166 variable regsd : std_logic_vector(31 downto 0); -- data from registers
167 variable dqm : std_logic_vector(7 downto 0);
168 variable raddr : std_logic_vector(12 downto 0);
169 variable adec : std_ulogic;
170 variable rams : std_logic_vector(1 downto 0);
171 variable ba : std_logic_vector(1 downto 0);
172 variable haddr : std_logic_vector(31 downto 0);
173 variable dout : std_logic_vector(31 downto 0);
174 variable hsize : std_logic_vector(1 downto 0);
175 variable hwrite : std_ulogic;
176 variable htrans : std_logic_vector(1 downto 0);
177 variable hready : std_ulogic;
178 variable vbdrive : std_logic_vector(31 downto 0);
179 variable bdrive : std_ulogic;
180 variable lline : std_logic_vector(2 downto 0);
181 variable lineburst : boolean;
182 variable haddr_tmp : std_logic_vector(31 downto 0);
183 variable arefresh : std_logic;
184 variable hwdata : std_logic_vector(31 downto 0);
185
186 begin
187
188 -- Variable default settings to avoid latches
189
190 v := r; startsd := '0'; v.hresp := HRESP_OKAY; vbdrive := rbdrive; arefresh := '0';
191 if BUS16 then
192 if (r.lhw = '1') then --muxes read data to correct part of the register.
193 v.hrdata(sdbits-1 downto 0) := sdi.data(sdbits-1 downto 0);
194 else
195 v.hrdata((sdbits*2)-1 downto sdbits) := sdi.data(sdbits-1 downto 0);
196 end if;
197 else
198 v.hrdata(sdbits-1 downto sdbits-32) := sdi.data(sdbits-1 downto sdbits-32);
199 v.hrdata(31 downto 0) := sdi.data(31 downto 0);
200 end if;
201 hwdata := ahbreadword(ahbsi.hwdata, r.haddr(4 downto 2)); v.hwdata := hwdata;
202 lline := not r.cfg.casdel & r.cfg.casdel & r.cfg.casdel;
203 if (pageburst = 0) or ((pageburst = 2) and r.cfg.pageburst = '0') then
204 lineburst := true;
205 else lineburst := false; end if;
206
207
208 if ((ahbsi.hready and ahbsi.hsel(hindex)) = '1') then
209 v.size := ahbsi.hsize(1 downto 0); v.hwrite := ahbsi.hwrite;
210 v.htrans := ahbsi.htrans;
211 if ahbsi.htrans(1) = '1' then
212 v.hio := ahbsi.hmbsel(1);
213 v.hsel := '1'; v.hready := v.hio;
214 end if;
215 v.haddr := ahbsi.haddr;
216 -- addr must be masked since address range can be smaller than
217 -- total banksize. this can result in wrong chip select being
218 -- asserted
219 for i in 31 downto 20 loop
220 v.haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
221 end loop;
222 end if;
223
224 if (r.hsel = '1') and (ahbsi.hready = '0') then
225 haddr := r.haddr; hsize := r.size;
226 htrans := r.htrans; hwrite := r.hwrite;
227 else
228 haddr := ahbsi.haddr; hsize := ahbsi.hsize(1 downto 0);
229 htrans := ahbsi.htrans; hwrite := ahbsi.hwrite;
230 -- addr must be masked since address range can be smaller than
231 -- total banksize. this can result in wrong chip select being
232 -- asserted
233 for i in 31 downto 20 loop
234 haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
235 end loop;
236 end if;
237 if fast = 1 then haddr := r.haddr; end if;
238
239 if ahbsi.hready = '1' then v.hsel := ahbsi.hsel(hindex); end if;
240
241 -- main state
242 if BUS16 then
243 case r.size is
244 when "00" => --bytesize
245 case r.haddr(0) is
246 when '0' => dqm := "11111101";
247 when others => dqm := "11111110";
248 end case;
249 when others => dqm := "11111100"; --halfword, word
250 end case;
251 else
252 case r.size is
253 when "00" =>
254 case r.haddr(1 downto 0) is
255 when "00" => dqm := "11110111";
256 when "01" => dqm := "11111011";
257 when "10" => dqm := "11111101";
258 when others => dqm := "11111110";
259 end case;
260 when "01" =>
261 if r.haddr(1) = '0' then dqm := "11110011"; else dqm := "11111100"; end if;
262 when others => dqm := "11110000";
263 end case;
264 end if;
265 --
266 -- case r.size is
267 -- when "00" =>
268 -- case r.haddr(1 downto 0) is
269 -- when "00" => dqm := "11111101"; lhw := '0'; --lhv := r.haddr(1)
270 -- when "01" => dqm := "11111110"; lhw := '0';
271 -- when "10" => dqm := "11111101"; lhw := '1';
272 -- when others => dqm := "11111110"; lhw := '1';
273 -- end case;
274 -- when "01" =>
275 -- dqm := "11111100";
276 -- if r.haddr(1) = '0' then
277 -- lhw := '0';
278 -- else
279 -- lhw := '1';
280 -- end if;
281 -- when others => dqm := "11111100"; --remember when word: lhw first 0 then 1
282 -- end case;
283 --
284 if BUS64 and (r.bsel = '1') then dqm := dqm(3 downto 0) & "1111"; end if;
285
286 -- main FSM
287
288 case r.mstate is
289 when midle =>
290 if ((v.hsel and htrans(1) and not v.hio) = '1') then
291 if (r.sdstate = sidle) and (r.cfg.command = "000")
292 and (r.cmstate = midle) and (v.hio = '0')
293 then
294 if fast = 0 then startsd := '1'; else v.startsd := '1'; end if;
295 v.mstate := active;
296 elsif ((r.sdstate = sref) or (r.sdstate = pd) or (r.sdstate = dpd))
297 and (r.cfg.command = "000") and (r.cmstate = midle) and (v.hio = '0')
298 then
299 v.startsd := '1';
300 if r.sdstate = dpd then -- Error response when on Deep Power-Down mode
301 v.hresp := HRESP_ERROR;
302 else
303 v.mstate := active;
304 end if;
305 end if;
306 end if;
307 when others => null;
308 end case;
309
310 startsd := startsd or r.startsd;
311
312 -- generate row and column address size
313
314 if BUS16 then
315 case r.cfg.csize is
316 when "00" => raddr := haddr(21 downto 9);-- case to check for bursting over row limit, since 1 row is 512 byte.
317 when "01" => raddr := haddr(22 downto 10);
318 when "10" => raddr := haddr(23 downto 11);
319 when others =>
320 if r.cfg.bsize = "110" then raddr := haddr(25 downto 13); --tänk
321 else raddr := haddr(24 downto 12); end if;
322 end case;
323 else
324 case r.cfg.csize is
325 when "00" => raddr := haddr(22 downto 10);
326 when "01" => raddr := haddr(23 downto 11);
327 when "10" => raddr := haddr(24 downto 12);
328 when others =>
329 if r.cfg.bsize = "111" then raddr := haddr(26 downto 14);
330 else raddr := haddr(25 downto 13); end if;
331 end case;
332 end if;
333
334 -- generate bank address
335 -- if BUS16 then --011
336 -- ba := genmux(r.cfg.bsize, haddr(26 downto 19)) &
337 -- genmux(r.cfg.bsize, haddr(25 downto 18));
338 -- else
339 ba := genmux(r.cfg.bsize, haddr(28 downto 21)) &
340 genmux(r.cfg.bsize, haddr(27 downto 20));
341 -- end if;
342
343 -- generate chip select
344
345 if BUS64 then
346 adec := genmux(r.cfg.bsize, haddr(30 downto 23));
347 v.bsel := genmux(r.cfg.bsize, r.haddr(29 downto 22));
348 else
349 adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
350 end if;
351 -- elsif BUS32 then
352 -- adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
353 -- else
354 -- adec := genmux(r.cfg.bsize, haddr(27 downto 20)); v.bsel := '0';
355 -- end if;
356
357 rams := adec & not adec;
358
359 -- sdram access FSM
360
361 if r.trfc /= "0000" then v.trfc := r.trfc - 1; end if;
362
363 if r.idlecnt /= "0000" then v.idlecnt := r.idlecnt - 1; end if;
364
365 case r.sdstate is
366
367 when sidle =>
368 if (startsd = '1') and (r.cfg.command = "000") and (r.cmstate = midle) then
369 -- if BUS16 then
370 -- v.address(16 downto 2) := '0' & ba & raddr(11 downto 0); --since 1 bit lower row => tot adress field 14 bits
371 -- else
372 v.address(16 downto 2) := ba & raddr; -- ba(16-15) & raddr(14-2) (2+13= 15 bits)
373 -- end if;
374 v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1;
375 v.startsd := '0';
376 elsif (r.idlecnt = "0000") and (r.cfg.command = "000")
377 and (r.cmstate = midle) and (r.cfg.mobileen(1) = '1') then
378 case r.cfg.pmode is
379 when PM_SR =>
380 v.cfg.cke := '0'; v.sdstate := sref;
381 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
382 v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc; -- Control minimum duration of Self Refresh mode (= tRAS)
383 when PM_PD => v.cfg.cke := '0'; v.sdstate := pd;
384 when PM_DPD =>
385 v.cfg.cke := '0'; v.sdstate := dpd;
386 v.sdcsn := (others => '0'); v.sdwen := '0'; v.rasn := '1'; v.casn := '1';
387 when others =>
388 end case;
389 end if;
390
391 when act1 =>
392 v.rasn := '1'; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
393 if r.cfg.casdel = '1' then v.sdstate := act2; else
394 v.sdstate := act3;
395 if not BUS16 then -- needs if, otherwise it might clock in incorrect write data to state act3_16
396 v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
397 end if;
398 end if;
399 if WPROTEN then
400 v.wprothit := sdi.wprot;
401 if sdi.wprot = '1' then v.hresp := HRESP_ERROR; end if;
402 end if;
403
404 when act2 =>
405 v.sdstate := act3;
406 if not BUS16 then
407 v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
408 end if;
409 if WPROTEN and (r.wprothit = '1') then
410 v.hresp := HRESP_ERROR; v.hready := '0';
411 end if;
412
413 when act3 =>
414 v.casn := '0';
415 if BUS16 then --HW adress needed to memory
416 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 1); --only allowed to use tot adressbits - ba bits
417 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 1); --only allowed to use tot adressbits - ba bits
418 v.lhw := r.haddr(1); -- 14-2 = 12 colummn bits => 13 downto 2
419 else
420 v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
421 end if;
422 v.dqm := dqm; v.burst := r.hready; -- ??
423
424 if r.hwrite = '1' then
425
426 if BUS16 then --16 bit
427 if r.size(1) = '1' then --word
428 v.hready := ahbsi.htrans(0) and ahbsi.htrans(1); --delayed this check 1 state to keep write data correct in act3_16
429 v.burst := ahbsi.htrans(0) and ahbsi.htrans(1);
430 v.sdstate := act3_16; -- goto state for second part of word transfer
431 -- v.lhw := '0'; --write MSB 16 bits to AMBA adress that ends with 00
432 else --halfword or byte
433 v.sdstate := act3_16; v.hready := '1';
434 end if;
435 else --32 bit or 64
436 v.sdstate := wr1;
437 if ahbsi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if;
438 end if;
439 v.sdwen := '0'; v.bdrive := '0'; --write
440 if WPROTEN and (r.wprothit = '1') then
441 v.hresp := HRESP_ERROR; v.hready := '1';
442 if BUS16 then v.sdstate := act3_16; else v.sdstate := wr1; end if;
443 v.sdwen := '1'; v.bdrive := '1'; v.casn := '1'; --skip write, remember hready high in next state
444 end if;
445 else v.sdstate := rd1; end if;
446
447 when act3_16 => --handle 16 bit and WORD write
448 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 2) & '1';
449 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 2) & '1';
450 v.lhw := '1';
451 if (r.hready and r.burst) = '1' and not (WPROTEN and (r.wprothit = '1')) then
452 v.hready := '0'; --kolla på transfertyp nonseq om vi vill delaya nedankoll.
453 if( ahbsi.htrans = "11" and
454 not ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) and
455 not ((r.haddr(9) xor ahbsi.haddr(9)) = '1' and r.cfg.csize = "00") ) then
456 v.sdstate := wr1_16;
457 end if;
458 elsif r.burst = '1' or (r.hready and not r.burst) = '1' then --terminate burst or single write
459 v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
460 v.dqm := (others => '1');
461 else -- complete single write
462 v.hready := '1';
463 v.sdstate := act3_16; --gick till wr1 förut
464 end if;
465
466 when wr1_16 =>
467 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 1);
468 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 1);
469 v.lhw := r.haddr(1);
470 v.sdstate := act3_16;
471 v.hready := '1';
472
473 when wr1 =>
474 v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
475 if (((r.burst and r.hready) = '1') and (r.htrans = "11"))
476 and not (WPROTEN and (r.wprothit = '1'))
477 then
478 v.hready := ahbsi.htrans(0) and ahbsi.htrans(1) and r.hready;
479 if ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) then -- exit on refresh
480 v.hready := '0';
481 end if;
482 else
483 v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
484 v.dqm := (others => '1');
485 end if;
486
487 when wr2 =>
488 if (r.cfg.trp = '0') then v.rasn := '0'; v.sdwen := '0'; end if;
489 v.sdstate := wr3;
490
491 when wr3 =>
492 if (r.cfg.trp = '1') then
493 v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr4;
494 else
495 v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1'; v.sdstate := sidle;
496 v.idlecnt := (others => '1');
497 end if;
498
499 when wr4 =>
500 v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
501 if (r.cfg.trp = '1') then v.sdstate := wr5;
502 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
503
504 when wr5 =>
505 v.sdstate := sidle; v.idlecnt := (others => '1');
506
507 when rd1 => --first read applied to sdram
508 v.casn := '1'; v.sdstate := rd7; --nop
509 if not BUS16 then --starting adress cannot be XXXX...111 since we have word burst in this case. and lowest bit always 0.
510 if lineburst and (ahbsi.htrans = "11") then
511 if r.haddr(4 downto 2) = "111" then
512 v.address(9 downto 5) := r.address(9 downto 5) + 1; --adds only within 1KB limit.
513 v.address(4 downto 2) := "000"; v.casn := '0';
514 end if;
515 end if;
516 end if;
517
518 when rd7 =>
519 v.casn := '1'; --nop
520 if BUS16 then
521 if r.cfg.casdel = '1' then --casdel3
522 v.sdstate := rd2;
523 if lineburst and (ahbsi.htrans = "11") then
524 if r.haddr(3 downto 1) = "110" then
525 v.address(10 downto 5) := r.address(10 downto 5) + 1;
526 v.address(4 downto 2) := "000"; v.casn := '0';
527 end if;
528 end if;
529 else --casdel2
530 v.sdstate := rd3;
531 if ahbsi.htrans /= "11" then
532 if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if;
533 elsif lineburst then
534 if r.haddr(3 downto 1) = "110" then
535 v.address(10 downto 5) := r.address(10 downto 5) + 1;
536 v.address(4 downto 2) := "000"; v.casn := '0';
537 end if;
538 end if;
539 end if;
540 else -- 32 bit or larger
541 if r.cfg.casdel = '1' then --casdel3
542 v.sdstate := rd2;
543 if lineburst and (ahbsi.htrans = "11") then
544 if r.haddr(4 downto 2) = "110" then
545 v.address(9 downto 5) := r.address(9 downto 5) + 1;
546 v.address(4 downto 2) := "000"; v.casn := '0';
547 end if;
548 end if;
549 else --casdel2
550 v.sdstate := rd3;
551 if ahbsi.htrans /= "11" then
552 if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if; --precharge
553 elsif lineburst then
554 if r.haddr(4 downto 2) = "110" then
555 v.address(9 downto 5) := r.address(9 downto 5) + 1;
556 v.address(4 downto 2) := "000"; v.casn := '0';
557 end if;
558 end if;
559 end if;
560 end if;
561
562 when rd2 =>
563 v.casn := '1'; v.sdstate := rd3;
564 if BUS16 then
565 if ahbsi.htrans /= "11" then
566 v.rasn := '0'; v.sdwen := '0'; v.dqm := (others => '1'); --precharge & DQM
567 --note that DQM always has 2 cycle delay before blocking data. So NP if we fetch second HW
568 end if;
569 else
570 if ahbsi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0'; v.dqm := (others => '1'); --precharge & DQM
571 elsif lineburst then
572 if r.haddr(4 downto 2) = "101" then
573 v.address(9 downto 5) := r.address(9 downto 5) + 1;
574 v.address(4 downto 2) := "000"; v.casn := '0';
575 end if;
576 end if;
577 end if;
578
579 when rd3 => --first read data from sdram output v.lhw := r.haddr(1);
580 v.casn := '1'; --if read before cas makes nop else if pre => no difference
581 if BUS16 then
582 --note if read is for halfwor or byte we dont want to read a second time but exit.
583 --if the read is a word we need to change LHW to one since the next read should be muxed in next cylcle.
584 -- if r.size(1) = '1' then --word v.hready := not r.size(1)
585 -- v.sdstate := rd4_16; v.hready := '0'; --hready low since just first part of a word
586 -- v.lhw := '1'; -- read low 16 next state
587 -- else --HW or byte
588 -- v.sdstate := rd4_16; v.hready := '1';
589 -- end if;
590 v.sdstate := rd4_16;
591 v.lhw := not r.lhw; --r.lhw is 0 for word, we should invert for next half of word.For HW or Byte v.lhw does not matter.
592 v.hready := not r.size(1); --if word transfer the r.size(1) is 1 and hready goes low.If HW or byte r.size(1)=0 => hready=1
593 if r.sdwen = '0' then
594 v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); -- make DSEL (NOP)
595 elsif lineburst and ((ahbsi.htrans = "11") and (r.cfg.casdel = '1')) then --only enter if cl3
596 if r.haddr(3 downto 1) = "100" then
597 v.address(10 downto 5) := r.address(10 downto 5) + 1;
598 v.address(4 downto 2) := "000"; v.casn := '0';
599 end if;
600 end if;
601 else --32 bit or larger
602 v.sdstate := rd4; v.hready := '1';
603 if r.sdwen = '0' then
604 v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); -- make DSEL (NOP)
605 elsif lineburst and (ahbsi.htrans = "11") and (r.casn = '1') then
606 if r.haddr(4 downto 2) = ("10" & not r.cfg.casdel) then
607 v.address(9 downto 5) := r.address(9 downto 5) + 1;
608 v.address(4 downto 2) := "000"; v.casn := '0';
609 end if;
610 end if;
611 end if;
612
613 when rd4_16 => --enter as word (r.hready is still 0) else 1. If hready one next transfer sampled into v.
614 --v.hready := '1';
615 v.hready := not r.hready;-- if Byte or HW exit with hready low. If word flip bit, makes correct exit with hready low.
616 v.lhw := not r.lhw; --r.lhw is one the first time we enter (taking care of second part of word)
617 v.casn := '1';
618 --quit on: Single transfer CL 2/3 (prcharge if CL 2 and timer was not 0)
619 if (ahbsi.htrans /= "11" and (r.hready = '1')) or
620 ((r.haddr(9) xor ahbsi.haddr(9)) = '1' and r.cfg.csize = "00" and r.hready = '1') or --probably dont have to check hready 1 since if 0 adresses equal.
621 ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100") and (r.hready = '1')) then --quit on: ST W/HW/BYTE OR
622 --v.hready := '0'; --if Byte or HW exit with hready low, if ST word exit with high.
623 v.dqm := (others => '1');
624 if r.sdcsn /= "11" then --not prechargeing
625 v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5; --precharge
626 else--exit
627 if r.cfg.trp = '1' then v.sdstate := rd6;
628 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
629 end if;
630 elsif lineburst then --NOTE: r.casn = 1 makes sure its the first halfword of a word that is checked (hready low)
631 if r.cfg.casdel = '0' then
632 if (r.haddr(3 downto 1) = "100") and (r.casn = '1') then --lline = 011 if casdel =1, 100 if casdel= 0
633 v.address(10 downto 5) := r.address(10 downto 5) + 1;
634 v.address(4 downto 2) := "000"; v.casn := '0';
635 end if;
636 else
637 if (r.haddr(3 downto 1) = "010") and (r.hready = '1') then --lline = 011 if casdel =1, 100 if casdel= 0
638 v.address(10 downto 5) := r.address(10 downto 5) + 1;
639 v.address(4 downto 2) := "000"; v.casn := '0';
640 end if;
641 end if;
642 end if;
643
644 when rd4 =>
645 v.hready := '1'; v.casn := '1';
646 if (ahbsi.htrans /= "11") or (r.sdcsn = "11") or
647 ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) -- exit on refresh
648 then
649 v.hready := '0'; v.dqm := (others => '1');
650 if (r.sdcsn /= "11") then
651 v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5;
652 else
653 if r.cfg.trp = '1' then v.sdstate := rd6;
654 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
655 end if;
656 elsif lineburst then
657 if (r.haddr(4 downto 2) = lline) and (r.casn = '1') then
658 v.address(9 downto 5) := r.address(9 downto 5) + 1;
659 v.address(4 downto 2) := "000"; v.casn := '0';
660 end if;
661 end if;
662
663 when rd5 =>
664 if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
665 v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := (others => '1');
666 v.casn := '1';
667
668 when rd6 =>
669 v.sdstate := sidle; v.idlecnt := (others => '1'); v.dqm := (others => '1');
670 v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1';
671
672 when sref =>
673 if (startsd = '1' and (r.hio = '0'))
674 or (r.cfg.command /= "000") or r.cfg.pmode /= PM_SR then
675 if r.trfc = "0000" then -- Minimum duration (= tRAS)
676 v.cfg.cke := '1';
677 v.sdcsn := (others => '0'); v.rasn := '1'; v.casn := '1';
678 end if;
679 if r.cfg.cke = '1' then
680 if (r.idlecnt = "0000") then -- tXSR ns with NOP
681 v.sdstate := sidle;
682 v.idlecnt := (others => '1');
683 v.sref_tmpcom := r.cfg.command;
684 v.cfg.command := "100";
685 end if;
686 else
687 v.idlecnt := r.cfg.txsr;
688 end if;
689 end if;
690
691 when pd =>
692 if (startsd = '1' and (r.hio = '0'))
693 or (r.cfg.command /= "000") or r.cfg.pmode /= PM_PD then
694 v.cfg.cke := '1';
695 v.sdstate := sidle;
696 v.idlecnt := (others => '1');
697 end if;
698
699 when dpd =>
700 v.sdcsn := (others => '1'); v.sdwen := '1'; v.rasn := '1'; v.casn := '1';
701 v.cfg.renable := '0';
702 if (startsd = '1' and r.hio = '0') then
703 v.hready := '1'; -- ack all accesses with Error response
704 v.startsd := '0';
705 v.hresp := HRESP_ERROR;
706 elsif r.cfg.pmode /= PM_DPD then
707 v.cfg.cke := '1';
708 if r.cfg.cke = '1' then
709 v.sdstate := sidle;
710 v.idlecnt := (others => '1');
711 v.cfg.renable := '1';
712 end if;
713 end if;
714
715 when others =>
716 v.sdstate := sidle; v.idlecnt := (others => '1');
717 end case;
718
719 -- sdram commands
720
721 case r.cmstate is
722 when midle =>
723 if r.sdstate = sidle then
724 case r.cfg.command is
725 when "010" => -- precharge
726 v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0';
727 v.address(12) := '1'; v.cmstate := active;
728 when "100" => -- auto-refresh
729 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
730 v.cmstate := active;
731 when "110" => -- Lodad Mode Reg
732 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
733 v.sdwen := '0'; v.cmstate := active;
734 if lineburst then
735 v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0011";
736 else
737 v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0111";
738 end if;
739 when "111" => -- Load Ext-Mode Reg
740 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
741 v.sdwen := '0'; v.cmstate := active;
742 v.address(16 downto 2) := "10000000" & r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0)
743 & r.cfg.pasr(2 downto 0);
744 when others => null;
745 end case;
746 end if;
747 when active =>
748 v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1';
749 v.sdwen := '1'; --v.cfg.command := "000";
750 v.cfg.command := r.sref_tmpcom; v.sref_tmpcom := "000";
751 v.cmstate := leadout; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
752 when leadout =>
753 if r.trfc = "0000" then v.cmstate := midle; end if;
754
755 end case;
756
757 -- sdram init
758
759 case r.istate is
760 when iidle =>
761 v.cfg.cke := '1';
762 if r.cfg.renable = '1' and r.cfg.cke = '1' then
763 v.cfg.command := "010"; v.istate := pre;
764 end if;
765 when pre =>
766 if r.cfg.command = "000" then
767 v.cfg.command := "100"; v.istate := ref; v.icnt := "111";
768 end if;
769 when ref =>
770 if r.cfg.command = "000" then
771 v.cfg.command := "100"; v.icnt := r.icnt - 1;
772 if r.icnt = "000" then v.istate := lmode; v.cfg.command := "110"; end if;
773 end if;
774 when lmode =>
775 if r.cfg.command = "000" then
776 if r.cfg.mobileen = "11" then
777 v.cfg.command := "111"; v.istate := emode;
778 else
779 v.istate := finish;
780 end if;
781 end if;
782 when emode =>
783 if r.cfg.command = "000" then
784 v.istate := finish;
785 end if;
786 when others =>
787 if r.cfg.renable = '0' and r.sdstate /= dpd then
788 v.istate := iidle;
789 end if;
790 end case;
791
792 if (ahbsi.hready and ahbsi.hsel(hindex) ) = '1' then
793 if ahbsi.htrans(1) = '0' then v.hready := '1'; end if;
794 end if;
795
796 if (r.hsel and r.hio and not r.hready) = '1' then v.hready := '1'; end if;
797
798 -- second part of main fsm
799
800 case r.mstate is
801 when active =>
802 if v.hready = '1' then
803 v.mstate := midle;
804 end if;
805 when others => null;
806 end case;
807
808 -- sdram refresh counter
809
810 -- pragma translate_off
811 if not is_x(r.cfg.refresh) then
812 -- pragma translate_on
813 if (r.cfg.renable = '1') and (r.istate = finish) and r.sdstate /= sref then
814 v.refresh := r.refresh - 1;
815 if (v.refresh(14) and not r.refresh(14)) = '1' then
816 v.refresh := r.cfg.refresh;
817 v.cfg.command := "100";
818 arefresh := '1';
819 end if;
820 end if;
821 -- pragma translate_off
822 end if;
823 -- pragma translate_on
824
825 -- AHB register access
826 -- if writing to IO space config regs. Just mapping write data to all config values in config reg
827 if (r.hsel and r.hio and r.hwrite and r.htrans(1)) = '1' then
828 if r.haddr(3 downto 2) = "00" then
829 if pageburst = 2 then v.cfg.pageburst := hwdata(17); end if;
830 v.cfg.command := hwdata(20 downto 18);
831 v.cfg.csize := hwdata(22 downto 21);
832 v.cfg.bsize := hwdata(25 downto 23);
833 v.cfg.casdel := hwdata(26);
834 v.cfg.trfc := hwdata(29 downto 27);
835 v.cfg.trp := hwdata(30);
836 v.cfg.renable := hwdata(31);
837 v.cfg.refresh := hwdata(14 downto 0);
838 v.refresh := (others => '0');
839 elsif r.haddr(3 downto 2) = "01" then
840 if r.cfg.mobileen(1) = '1' and mobile /= 3 then v.cfg.mobileen(0) := hwdata(31); end if;
841 if r.cfg.pmode = "000" then
842 v.cfg.cke := hwdata(30);
843 end if;
844 if r.cfg.mobileen(1) = '1' then
845 v.cfg.txsr := hwdata(23 downto 20);
846 v.cfg.pmode := hwdata(18 downto 16);
847 v.cfg.ds(3 downto 2) := hwdata( 6 downto 5);
848 v.cfg.tcsr(3 downto 2) := hwdata( 4 downto 3);
849 v.cfg.pasr(5 downto 3) := hwdata( 2 downto 0);
850 end if;
851 end if;
852 end if;
853
854 -- Disable CS and DPD when Mobile SDR is Disabled
855 if r.cfg.mobileen(0) = '0' then v.cfg.pmode(2) := '0'; end if;
856
857 -- Update EMR when ds, tcsr or pasr change
858 if r.cfg.command = "000" and arefresh = '0' and r.cfg.mobileen(0) = '1' then
859 if r.cfg.ds(1 downto 0) /= r.cfg.ds(3 downto 2) then
860 v.cfg.command := "111"; v.cfg.ds(1 downto 0) := r.cfg.ds(3 downto 2);
861 end if;
862 if r.cfg.tcsr(1 downto 0) /= r.cfg.tcsr(3 downto 2) then
863 v.cfg.command := "111"; v.cfg.tcsr(1 downto 0) := r.cfg.tcsr(3 downto 2);
864 end if;
865 if r.cfg.pasr(2 downto 0) /= r.cfg.pasr(5 downto 3) then
866 v.cfg.command := "111"; v.cfg.pasr(2 downto 0) := r.cfg.pasr(5 downto 3);
867 end if;
868 end if;
869
870 regsd := (others => '0');
871 --reads out config registers (r/w does not matter) according to manual depending on address, notice generic determines data width.
872 if r.haddr(3 downto 2) = "00" then
873 regsd(31 downto 18) := r.cfg.renable & r.cfg.trp & r.cfg.trfc &
874 r.cfg.casdel & r.cfg.bsize & r.cfg.csize & r.cfg.command;
875 if not lineburst then regsd(17) := '1'; end if;
876 regsd(16) := r.cfg.mobileen(1);
877 if BUS64 then regsd(15) := '1'; end if;
878 regsd(14 downto 0) := r.cfg.refresh;
879 elsif r.haddr(3 downto 2) = "01" then
880 regsd(31) := r.cfg.mobileen(0);
881 regsd(30) := r.cfg.cke;
882 regsd(23 downto 0) := r.cfg.txsr & '0' & r.cfg.pmode & "000000000" &
883 r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0) & r.cfg.pasr(2 downto 0);
884 end if;
885
886 if (r.hsel and r.hio) = '1' then dout := regsd;
887 else
888 if BUS64 and r.bsel = '1' then dout := r.hrdata(63 downto 32);
889 else dout := r.hrdata(31 downto 0); end if;
890 end if;
891
892 v.nbdrive := not v.bdrive;
893
894 if oepol = 1 then bdrive := r.nbdrive; vbdrive := (others => v.nbdrive);
895 else bdrive := r.bdrive; vbdrive := (others => v.bdrive);end if;
896
897 -- reset
898
899 if rst = '0' then
900 v.sdstate := sidle;
901 v.mstate := midle;
902 v.istate := iidle;
903 v.cmstate := midle;
904 v.hsel := '0';
905 v.cfg.command := "000";
906 v.cfg.csize := "01";
907 v.cfg.bsize := "011";
908 v.cfg.casdel := '1';
909 v.cfg.trfc := "111";
910 if pwron = 1 then v.cfg.renable := '1';
911 else v.cfg.renable := '0'; end if;
912 v.cfg.trp := '1';
913 v.dqm := (others => '1');
914 v.sdwen := '1';
915 v.rasn := '1';
916 v.casn := '1';
917 v.hready := '1';
918 v.bsel := '0';
919 v.startsd := '0';
920 if (pageburst = 2) then
921 v.cfg.pageburst := '0';
922 end if;
923 if mobile >= 2 then v.cfg.mobileen := "11";
924 elsif mobile = 1 then v.cfg.mobileen := "10";
925 else v.cfg.mobileen := "00"; end if;
926 v.cfg.txsr := (others => '1');
927 v.cfg.pmode := (others => '0');
928 v.cfg.ds := (others => '0');
929 v.cfg.tcsr := (others => '0');
930 v.cfg.pasr := (others => '0');
931 if mobile >= 2 then v.cfg.cke := '0';
932 else v.cfg.cke := '1'; end if;
933 v.sref_tmpcom := "000";
934 v.idlecnt := (others => '1');
935 end if;
936
937 ri <= v;
938 ribdrive <= vbdrive;
939
940 ahbso.hready <= r.hready;
941 ahbso.hresp <= r.hresp;
942 ahbso.hrdata <= ahbdrivedata(dout);
943
944 end process;
945
946 --sdo.sdcke <= (others => '1');
947 sdo.sdcke <= (others => r.cfg.cke);
948 ahbso.hconfig <= hconfig;
949 ahbso.hirq <= (others => '0');
950 ahbso.hindex <= hindex;
951 ahbso.hsplit <= (others => '0');
952
953 -- Quick hack to get rid of undriven signal warnings. Check this for future
954 -- merge with main sdctrl.
955 drivehack : block
956 begin
957 sdo.qdrive <= '0';
958 sdo.nbdrive <= '0';
959 sdo.ce <= '0';
960 sdo.moben <= '0';
961 sdo.cal_rst <= '0';
962 sdo.oct <= '0';
963 sdo.xsdcsn <= (others => '1');
964 sdo.data(127 downto 16) <= (others => '0');
965 sdo.cb <= (others => '0');
966 sdo.ba <= (others => '0');
967 sdo.sdck <= (others => '0');
968 sdo.cal_en <= (others => '0');
969 sdo.cal_inc <= (others => '0');
970 sdo.cal_pll <= (others => '0');
971 sdo.odt <= (others => '0');
972 sdo.conf <= (others => '0');
973 sdo.vcbdrive <= (others => '0');
974 sdo.dqs_gate <= '0';
975 sdo.cbdqm <= (others => '0');
976 sdo.cbcal_en <= (others => '0');
977 sdo.cbcal_inc <= (others => '0');
978 sdo.read_pend <= (others => '0');
979 sdo.regwdata <= (others => '0');
980 sdo.regwrite <= (others => '0');
981 end block drivehack;
982
983 regs : process(clk, rst) begin
984 if rising_edge(clk) then
985 r <= ri; rbdrive <= ribdrive;
986 if rst = '0' then r.icnt <= (others => '0'); end if;
987 end if;
988 if (rst = '0') then
989 r.sdcsn <= (others => '1'); r.bdrive <= '1'; r.nbdrive <= '0';
990 if oepol = 0 then rbdrive <= (others => '1');
991 else rbdrive <= (others => '0'); end if;
992 end if;
993 end process;
994
995 rgen : if not SDINVCLK generate
996 sdo.address <= r.address;
997 sdo.bdrive <= r.nbdrive when oepol = 1 else r.bdrive;
998 sdo.vbdrive <= zero32 & rbdrive;
999 sdo.sdcsn <= r.sdcsn;
1000 sdo.sdwen <= r.sdwen;
1001 sdo.dqm <= "11111111" & r.dqm;
1002 sdo.rasn <= r.rasn;
1003 sdo.casn <= r.casn;
1004
1005 mux16_wrdata : if BUS16 generate --mux data depending on Low/High HW
1006 sdo.data(15 downto 0) <= r.hwdata(15 downto 0) when r.lhw = '1' else r.hwdata(31 downto 16);
1007 end generate;
1008
1009 wrdata : if not BUS16 generate
1010 drivebus: for i in 0 to sdbits/64 generate
1011 sdo.data(31+32*i downto 32*i) <= r.hwdata;
1012 end generate;
1013 end generate;
1014 end generate;
1015
1016 ngen : if SDINVCLK generate
1017 nregs : process(clk, rst) begin
1018 if falling_edge(clk) then
1019 sdo.address <= r.address;
1020 if oepol = 1 then sdo.bdrive <= r.nbdrive;
1021 else sdo.bdrive <= r.bdrive; end if;
1022 sdo.vbdrive <= zero32 & rbdrive;
1023 sdo.sdcsn <= r.sdcsn;
1024 sdo.sdwen <= r.sdwen;
1025 sdo.dqm <= "11111111" & r.dqm;
1026 sdo.rasn <= r.rasn;
1027 sdo.casn <= r.casn;
1028 if BUS16 then --mux data depending on Low/High HW
1029 if (r.lhw ='1') then
1030 sdo.data(15 downto 0) <= r.hwdata(15 downto 0);
1031 else
1032 sdo.data(15 downto 0) <= r.hwdata(31 downto 16);
1033 end if;
1034 end if;
1035
1036 if not BUS16 then
1037 for i in 0 to sdbits/64 loop
1038 sdo.data(31+32*i downto 32*i) <= r.hwdata;
1039 end loop;
1040 end if;
1041 end if;
1042 if rst = '0' then sdo.sdcsn <= (others => '1'); end if;
1043 end process;
1044 end generate;
1045
1046 -- pragma translate_off
1047 bootmsg : report_version
1048 generic map ("sdctrl16" & tost(hindex) &
1049 ": PC133 SDRAM controller rev " & tost(REVISION));
1050 -- pragma translate_on
1051
1052 end;
1053
@@ -0,0 +1,224
1 ------------------------------------------------------------------------------
2 -- LEON3 Demonstration design test bench
3 -- Copyright (C) 2004 Jiri Gaisler, Gaisler Research
4 ------------------------------------------------------------------------------
5 ------------------------------------------------------------------------------
6 -- This file is a part of the GRLIB VHDL IP LIBRARY
7 -- Copyright (C) 2003 - 2008, Gaisler Research
8 -- Copyright (C) 2008 - 2014, Aeroflex Gaisler
9 -- Copyright (C) 2015 - 2016, Cobham Gaisler
10 --
11 -- This program is free software; you can redistribute it and/or modify
12 -- it under the terms of the GNU General Public License as published by
13 -- the Free Software Foundation; either version 2 of the License, or
14 -- (at your option) any later version.
15 --
16 -- This program is distributed in the hope that it will be useful,
17 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
18 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 -- GNU General Public License for more details.
20 --
21 -- You should have received a copy of the GNU General Public License
22 -- along with this program; if not, write to the Free Software
23 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25 library ieee;
26 use ieee.std_logic_1164.all;
27 use ieee.numeric_std.all;
28 library gaisler;
29 use gaisler.libdcom.all;
30 use gaisler.sim.all;
31 use work.debug.all;
32 library techmap;
33 use techmap.gencomp.all;
34 library micron;
35 use micron.components.all;
36 library grlib;
37 use grlib.stdlib.all;
38
39 use work.config.all; -- configuration
40
41
42 entity testbench is
43 generic (
44 fabtech : integer := CFG_FABTECH;
45 memtech : integer := CFG_MEMTECH;
46 padtech : integer := CFG_PADTECH;
47 clktech : integer := CFG_CLKTECH;
48 disas : integer := CFG_DISAS; -- Enable disassembly to console
49 dbguart : integer := CFG_DUART; -- Print UART on console
50 pclow : integer := CFG_PCLOW;
51
52 clkperiod : integer := 20; -- system clock period
53 romdepth : integer := 22 -- rom address depth (flash 4 MB)
54 -- sramwidth : integer := 32; -- ram data width (8/16/32)
55 -- sramdepth : integer := 20; -- ram address depth
56 -- srambanks : integer := 2 -- number of ram banks
57 );
58 end;
59
60 architecture behav of testbench is
61
62 constant promfile : string := "prom.srec"; -- rom contents
63 constant sramfile : string := "ram.srec"; -- ram contents
64 constant sdramfile : string := "ram.srec"; -- sdram contents
65
66
67 signal SW : std_logic_vector(4 downto 1);
68 signal clk : std_logic := '0';
69 signal Rst : std_logic := '0'; -- Reset
70 constant ct : integer := clkperiod/2;
71
72 signal address : std_logic_vector(21 downto 0);
73 signal data : std_logic_vector(31 downto 24);
74
75 signal romsn : std_logic;
76 signal oen : std_logic;
77 signal writen : std_logic;
78 signal dsuen, dsutx, dsurx, dsubre, dsuact : std_logic;
79 signal dsurst : std_logic;
80 signal error : std_logic;
81
82 signal sdcke : std_logic;
83 signal sdcsn : std_logic;
84 signal sdwen : std_logic; -- write en
85 signal sdrasn : std_logic; -- row addr stb
86 signal sdcasn : std_logic; -- col addr stb
87 signal dram_ldqm : std_logic;
88 signal dram_udqm : std_logic;
89 signal sdclk : std_logic;
90 signal dram_ba : std_logic_vector(1 downto 0);
91
92 signal FTDI_RXF : std_logic;
93 signal FTDI_TXE : std_logic;
94 signal FTDI_SIWUA : std_logic;
95 signal FTDI_WR : std_logic;
96 signal FTDI_RD : std_logic;
97 signal FTDI_D : std_logic_vector(7 downto 0):=(others=>'Z');
98
99 constant lresp : boolean := false;
100
101
102 signal sa : std_logic_vector(12 downto 0);
103 signal sd : std_logic_vector(15 downto 0);
104
105
106 begin
107
108 clk <= not clk after ct * 1 ns; --50 MHz clk
109 rst <= dsurst; --reset
110 dsuen <= '1';
111 dsubre <= '1'; -- inverted on the board
112 sw(1) <= rst;
113
114 d3 : entity work.leon3mp
115 generic map ( fabtech, memtech, padtech, clktech, disas, dbguart, pclow )
116 port map (
117 CLK50 => clk,
118 LEDS => open,
119 SW => SW,
120 dram_addr => sa,
121 dram_ba_0 => dram_ba(0),
122 dram_ba_1 => dram_ba(1),
123 dram_dq => sd(15 downto 0),
124 dram_clk => sdclk,
125 dram_cke => sdcke,
126 dram_cs_n => sdcsn,
127 dram_we_n => sdwen,
128 dram_ras_n => sdrasn,
129 dram_cas_n => sdcasn,
130 dram_ldqm => dram_ldqm,
131 dram_udqm => dram_udqm,
132 uart_txd => dsutx,
133 uart_rxd => dsurx,
134
135 FTDI_RXF => FTDI_RXF,
136 FTDI_TXE => FTDI_TXE,
137 FTDI_SIWUA => FTDI_SIWUA,
138 FTDI_WR => FTDI_WR,
139 FTDI_RD => FTDI_RD,
140 FTDI_D => FTDI_D
141 );
142
143 u1: entity work.mt48lc16m16a2 generic map (addr_bits => 13, col_bits => 9, index => 1024, fname => sdramfile)
144 PORT MAP(
145 Dq => sd(15 downto 0), Addr => sa(12 downto 0),
146 Ba => dram_ba, Clk => sdclk, Cke => sdcke,
147 Cs_n => sdcsn, Ras_n => sdrasn, Cas_n => sdcasn, We_n => sdwen,
148 Dqm(0) => dram_ldqm, Dqm(1) => dram_udqm );
149
150
151
152 error <= 'H'; -- ERROR pull-up
153
154 iuerr : process
155 begin
156 wait for 2500 ns;
157 if to_x01(error) = '1' then wait on error; end if;
158 assert (to_x01(error) = '1')
159 report "*** IU in error mode, simulation halted ***"
160 severity failure ;
161 end process;
162
163 data <= buskeep(data) after 5 ns;
164 sd <= buskeep(sd) after 5 ns;
165
166 testftdi : process
167 procedure ftdi_write(signal FTDI_RXF : out std_logic; signal FTDI_RD : in std_logic; value : integer; signal FTDI_D: out std_logic_vector(7 downto 0)) is
168 begin
169 FTDI_RXF <= '0';
170 wait until FTDI_RD = '0';
171 wait for 14 ns;
172 FTDI_D <= conv_std_logic_vector(value,8);
173 wait for 16 ns;
174 FTDI_D <= (others=>'Z');
175 wait until FTDI_RD = '1';
176 FTDI_RXF <= '1';
177 wait for 3 ns;
178 end;
179 procedure dcom_ftdi_write_reg(signal FTDI_RXF : out std_logic; signal FTDI_RD : in std_logic; address : std_logic_vector(31 downto 0); value : std_logic_vector(31 downto 0); signal FTDI_D: out std_logic_vector(7 downto 0)) is
180 begin
181 ftdi_write(FTDI_RXF,FTDI_RD,16#C0#,FTDI_D);
182 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(31 downto 24))),FTDI_D);
183 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(23 downto 16))),FTDI_D);
184 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(15 downto 8))),FTDI_D);
185 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(7 downto 0))),FTDI_D);
186 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(value(31 downto 24))),FTDI_D);
187 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(value(23 downto 16))),FTDI_D);
188 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(value(15 downto 8))),FTDI_D);
189 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(value(7 downto 0))),FTDI_D);
190
191 end;
192 procedure dcom_ftdi_read_reg(signal FTDI_RXF : out std_logic; signal FTDI_RD : in std_logic; address : std_logic_vector(31 downto 0); signal FTDI_D: out std_logic_vector(7 downto 0)) is
193 begin
194 ftdi_write(FTDI_RXF,FTDI_RD,16#80#,FTDI_D);
195 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(31 downto 24))),FTDI_D);
196 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(23 downto 16))),FTDI_D);
197 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(15 downto 8))),FTDI_D);
198 ftdi_write(FTDI_RXF,FTDI_RD,to_integer(UNSIGNED(address(7 downto 0))),FTDI_D);
199 end;
200 begin
201 FTDI_D <= (others=>'Z');
202 dsurst <= '0';
203 FTDI_RXF <= '1';
204 wait for 100 ns;
205 dsurst <= '1';
206 wait for 100 ns;
207 dcom_ftdi_read_reg(FTDI_RXF,FTDI_RD,X"80000000",FTDI_D);
208 dcom_ftdi_read_reg(FTDI_RXF,FTDI_RD,X"80000004",FTDI_D);
209 dcom_ftdi_read_reg(FTDI_RXF,FTDI_RD,X"80000008",FTDI_D);
210 dcom_ftdi_read_reg(FTDI_RXF,FTDI_RD,X"8000000C",FTDI_D);
211 dcom_ftdi_read_reg(FTDI_RXF,FTDI_RD,X"80000010",FTDI_D);
212 wait;
213 end process;
214
215 txe: process
216 begin
217 FTDI_TXE <= '0';
218 wait until FTDI_WR = '0';
219 wait for 14 ns;
220 FTDI_TXE <= '1';
221 wait for 49 ns;
222 end process;
223 end ;
224
@@ -0,0 +1,77
1 VHDLIB=../..
2 SELFDIR := $(dir $(lastword $(MAKEFILE_LIST)))
3 SCRIPTSDIR=$(VHDLIB)/scripts/
4 GRLIB := $(shell sh $(VHDLIB)/scripts/lpp_relpath.sh)
5 TOP=leon3mp
6 BOARD=MiniSpartan6p
7 DESIGN=leon3-MiniSpartan6p
8 include $(VHDLIB)/boards/$(BOARD)/Makefile.inc
9 DEVICE=$(PART)-$(PACKAGE)$(SPEED)
10 UCF=withSPW.ucf
11 UCF_PLANAHEAD=$(UCF)
12 QSF=$(GRLIB)/boards/$(BOARD)/$(TOP).qsf
13 EFFORT=high
14 XSTOPT=-uc leon3mp.xcf
15 SYNPOPT="set_option -pipe 1; set_option -retiming 1; set_option -write_apr_constraint 0"
16
17
18 VHDLOPTSYNFILES = sdctrl16.vhd config.vhd leon3mp.vhd
19
20 VHDLSIMFILES=mt48lc16m16a2.vhd testbench.vhd
21
22 SIMTOP=testbench
23 SDCFILE=$(GRLIB)/boards/$(BOARD)/default.sdc
24 BITGEN=$(VHDLIB)/boards/$(BOARD)/default.ut
25
26 TECHLIBS = unisim
27
28 LIBSKIP = core1553bbc core1553brm core1553brt gr1553 corePCIF \
29 tmtc openchip hynix ihp gleichmann usbhc fmf ftlib gsi
30
31 DIRSKIP = b1553 pcif leon2 leon2ft crypto satcan ddr usb ata i2c \
32 pci grusbhc haps slink ascs can pwm greth coremp7 ac97 atf \
33 grlfpc \
34 ./dsp/lpp_fft_rtax \
35 ./amba_lcd_16x2_ctrlr \
36 ./general_purpose/lpp_AMR \
37 ./general_purpose/lpp_balise \
38 ./general_purpose/lpp_delay \
39 ./lpp_bootloader \
40 ./lpp_sim/CY7C1061DV33 \
41 ./lpp_uart \
42 ./lpp_usb \
43 ./dsp/lpp_fft \
44 ./lpp_leon3_soc \
45 ./lpp_debug_lfr
46
47 FILESKIP = i2cmst.vhd \
48 APB_MULTI_DIODE.vhd \
49 APB_MULTI_DIODE.vhd \
50 Top_MatrixSpec.vhd \
51 APB_FFT.vhd \
52 lpp_lfr_ms_FFT.vhd \
53 lpp_lfr_apbreg.vhd \
54 CoreFFT.vhd \
55 lpp_lfr_ms.vhd \
56 lpp_lfr_sim_pkg.vhd \
57 mtie_maps.vhd \
58 ftsrctrlc.vhd \
59 ftsdctrl.vhd \
60 ftsrctrl8.vhd \
61 ftmctrl.vhd \
62 ftsdctrl64.vhd \
63 ftahbram.vhd \
64 ftahbram2.vhd \
65 sramft.vhd \
66 nandfctrlx.vhd
67
68 include $(GRLIB)/bin/Makefile
69
70 ################## project specific targets ##########################
71
72 load-ram:
73 xc3sprog -c ftdi -p0 leon3mp.bit
74
75 load-flash:
76 xc3sprog -c ftdi -p0 $(VHDLIB)/boards/$(BOARD)/bscan_spi_s6lx25_ftg256.bit
77 xc3sprog -c ftdi -I leon3mp.bit
@@ -0,0 +1,66
1 This LEON3 design is tailored to the Scarab Hardware [MiniSpartan6+](https://www.scarabhardware.com/minispartan6/) board.
2
3 Simulation and synthesis
4 ------------------------
5
6 This design tries to use as much as possible free (as in freedom) tools and at least free (as in free beer) when impossible.
7
8
9 Note that the simulation doesn't work as expected yet.
10
11
12 To build the design:
13 ```bash
14 make ise
15 ```
16
17 To load into FPGA RAM:
18 ```bash
19 make load-ram
20 ```
21
22 To load into FPGA Flash:
23 ```bash
24 make load-flash
25 ```
26
27 Design specifics
28 ----------------
29
30 * The AHB and processor is clocked from the 50 MHz clock.
31
32 * The SDRAM is working with the sdctrl16 memory controller taken from leon3-altera-de2-ep2c35 design.
33
34 * The UART DSU interface ie enabled and connected to interface B of ft2232H chip.
35 Start GRMON with -uart /dev/ttyUSB1
36
37 * Output from GRMON2 should look similar to this:
38
39 ```bash
40 GRMON2 LEON debug monitor v2.0.80-beta 64-bit eval version
41
42 Copyright (C) 2016 Cobham Gaisler - All rights reserved.
43 For latest updates, go to http://www.gaisler.com/
44 Comments or bug-reports to support@gaisler.com
45
46 This eval version will expire on 18/04/2017
47
48 using port /dev/ttyUSB1 @ 115200 baud
49 GRLIB build version: 4164
50 Detected frequency: 50 MHz
51
52 Component Vendor
53 LEON3 SPARC V8 Processor Cobham Gaisler
54 AHB Debug UART Cobham Gaisler
55 AHB/APB Bridge Cobham Gaisler
56 LEON3 Debug Support Unit Cobham Gaisler
57 PC133 SDRAM Controller Cobham Gaisler
58 Multi-processor Interrupt Ctrl. Cobham Gaisler
59 Modular Timer Unit Cobham Gaisler
60 General Purpose I/O port Cobham Gaisler
61
62 Use command 'info sys' to print a detailed report of attached cores
63
64 grmon2>
65
66 ``` No newline at end of file
@@ -0,0 +1,11
1 F0 -> L46P -> DOUT+ -> 9 -> Grey
2 F1 -> L46N -> DOUT- -> 5 -> Yellow
3
4 F5 -> L40P -> SOUT+ -> 8 -> Violet
5 F7 -> L40N -> SOUT- -> 4 -> Orange
6
7 F3 -> L53P -> SIN+ -> 2 -> Brown
8 F6 -> L53N -> SIN- -> 7 -> Blue
9
10 F9 -> L39N -> DIN- -> 6 -> Green
11 F10 -> L39P -> DIN+ -> 1 -> Black
@@ -0,0 +1,162
1
2
3
4 -----------------------------------------------------------------------------
5 -- LEON3 Demonstration design test bench configuration
6 -- Copyright (C) 2009 Aeroflex Gaisler
7 ------------------------------------------------------------------------------
8
9
10 library techmap;
11 use techmap.gencomp.all;
12
13 package config is
14 -- Technology and synthesis options
15 constant CFG_FABTECH : integer := spartan6;
16 constant CFG_MEMTECH : integer := spartan6;
17 constant CFG_PADTECH : integer := spartan6;
18 constant CFG_TRANSTECH : integer := GTP0;
19 constant CFG_NOASYNC : integer := 0;
20 constant CFG_SCAN : integer := 0;
21 -- Clock generator
22 constant CFG_CLKTECH : integer := spartan6;
23 constant CFG_CLKMUL : integer := (3);
24 constant CFG_CLKDIV : integer := (2);
25 constant CFG_OCLKDIV : integer := 1;
26 constant CFG_OCLKBDIV : integer := 0;
27 constant CFG_OCLKCDIV : integer := 0;
28 constant CFG_PCIDLL : integer := 0;
29 constant CFG_PCISYSCLK: integer := 0;
30 constant CFG_CLK_NOFB : integer := 0;
31 -- LEON3 processor core
32 constant CFG_LEON3 : integer := 1;
33 constant CFG_NCPU : integer := (1);
34 constant CFG_NWIN : integer := (8);
35 constant CFG_V8 : integer := 2 + 4*0;
36 constant CFG_MAC : integer := 0;
37 constant CFG_BP : integer := 1;
38 constant CFG_SVT : integer := 1;
39 constant CFG_RSTADDR : integer := 16#00000#;
40 constant CFG_LDDEL : integer := (2);
41 constant CFG_NOTAG : integer := 1;
42 constant CFG_NWP : integer := (0);
43 constant CFG_PWD : integer := 0*2;
44 constant CFG_FPU : integer := 0 + 16*0 + 32*0;
45 constant CFG_GRFPUSH : integer := 0;
46 constant CFG_ICEN : integer := 1;
47 constant CFG_ISETS : integer := 1;
48 constant CFG_ISETSZ : integer := 8;
49 constant CFG_ILINE : integer := 8;
50 constant CFG_IREPL : integer := 0;
51 constant CFG_ILOCK : integer := 0;
52 constant CFG_ILRAMEN : integer := 0;
53 constant CFG_ILRAMADDR: integer := 16#8E#;
54 constant CFG_ILRAMSZ : integer := 1;
55 constant CFG_DCEN : integer := 1;
56 constant CFG_DSETS : integer := 1;
57 constant CFG_DSETSZ : integer := 8;
58 constant CFG_DLINE : integer := 8;
59 constant CFG_DREPL : integer := 0;
60 constant CFG_DLOCK : integer := 0;
61 constant CFG_DSNOOP : integer := 0 + 0*2 + 4*0;
62 constant CFG_DFIXED : integer := 16#0#;
63 constant CFG_DLRAMEN : integer := 0;
64 constant CFG_DLRAMADDR: integer := 16#8F#;
65 constant CFG_DLRAMSZ : integer := 1;
66 constant CFG_MMUEN : integer := 0;
67 constant CFG_ITLBNUM : integer := 8;
68 constant CFG_DTLBNUM : integer := 2;
69 constant CFG_TLB_TYPE : integer := 1 + 0*2;
70 constant CFG_TLB_REP : integer := 1;
71 constant CFG_MMU_PAGE : integer := 0;
72 constant CFG_DSU : integer := 1;
73 constant CFG_ITBSZ : integer := 0 + 64*0;
74 constant CFG_ATBSZ : integer := 0;
75 constant CFG_AHBPF : integer := 0;
76 constant CFG_LEON3FT_EN : integer := 0;
77 constant CFG_IUFT_EN : integer := 0;
78 constant CFG_FPUFT_EN : integer := 0;
79 constant CFG_RF_ERRINJ : integer := 0;
80 constant CFG_CACHE_FT_EN : integer := 0;
81 constant CFG_CACHE_ERRINJ : integer := 0;
82 constant CFG_LEON3_NETLIST: integer := 0;
83 constant CFG_DISAS : integer := 0 + 0;
84 constant CFG_PCLOW : integer := 2;
85 constant CFG_STAT_ENABLE : integer := 0;
86 constant CFG_STAT_CNT : integer := 1;
87 constant CFG_STAT_NMAX : integer := 0;
88 constant CFG_STAT_DSUEN : integer := 0;
89 constant CFG_NP_ASI : integer := 0;
90 constant CFG_WRPSR : integer := 0;
91 constant CFG_ALTWIN : integer := 0;
92 constant CFG_REX : integer := 0;
93 -- AMBA settings
94 constant CFG_DEFMST : integer := (0);
95 constant CFG_RROBIN : integer := 1;
96 constant CFG_SPLIT : integer := 1;
97 constant CFG_FPNPEN : integer := 0;
98 constant CFG_AHBIO : integer := 16#FFF#;
99 constant CFG_APBADDR : integer := 16#800#;
100 constant CFG_AHB_MON : integer := 0;
101 constant CFG_AHB_MONERR : integer := 0;
102 constant CFG_AHB_MONWAR : integer := 0;
103 constant CFG_AHB_DTRACE : integer := 0;
104 -- DSU UART
105 constant CFG_AHB_UART : integer := 1;
106 -- JTAG based DSU interface
107 constant CFG_AHB_JTAG : integer := 1;
108 -- Xilinx MIG
109 constant CFG_MIG_DDR2 : integer := 1;
110 constant CFG_MIG_RANKS : integer := (1);
111 constant CFG_MIG_COLBITS : integer := (10);
112 constant CFG_MIG_ROWBITS : integer := (13);
113 constant CFG_MIG_BANKBITS: integer := (2);
114 constant CFG_MIG_HMASK : integer := 16#FC0#;
115 -- AHB ROM
116 constant CFG_AHBROMEN : integer := 1;
117 constant CFG_AHBROPIP : integer := 0;
118 constant CFG_AHBRODDR : integer := 16#000#;
119 constant CFG_ROMADDR : integer := 16#100#;
120 constant CFG_ROMMASK : integer := 16#E00# + 16#100#;
121 -- AHB RAM
122 constant CFG_AHBRAMEN : integer := 1;
123 constant CFG_AHBRSZ : integer := 4;
124 constant CFG_AHBRADDR : integer := 16#A00#;
125 constant CFG_AHBRPIPE : integer := 0;
126 -- UART 1
127 constant CFG_UART1_ENABLE : integer := 1;
128 constant CFG_UART1_FIFO : integer := 4;
129 -- LEON3 interrupt controller
130 constant CFG_IRQ3_ENABLE : integer := 1;
131 constant CFG_IRQ3_NSEC : integer := 0;
132 -- Modular timer
133 constant CFG_GPT_ENABLE : integer := 1;
134 constant CFG_GPT_NTIM : integer := (2);
135 constant CFG_GPT_SW : integer := (8);
136 constant CFG_GPT_TW : integer := (32);
137 constant CFG_GPT_IRQ : integer := (8);
138 constant CFG_GPT_SEPIRQ : integer := 1;
139 constant CFG_GPT_WDOGEN : integer := 0;
140 constant CFG_GPT_WDOG : integer := 16#0#;
141 -- GPIO port
142 constant CFG_GRGPIO_ENABLE : integer := 1;
143 constant CFG_GRGPIO_IMASK : integer := 16#0000#;
144 constant CFG_GRGPIO_WIDTH : integer := 1;
145
146 -- SPI controller
147 constant CFG_SPICTRL_ENABLE : integer := 1;
148 constant CFG_SPICTRL_NUM : integer := (1);
149 constant CFG_SPICTRL_SLVS : integer := (1);
150 constant CFG_SPICTRL_FIFO : integer := (2);
151 constant CFG_SPICTRL_SLVREG : integer := 1;
152 constant CFG_SPICTRL_ODMODE : integer := 1;
153 constant CFG_SPICTRL_AM : integer := 0;
154 constant CFG_SPICTRL_ASEL : integer := 0;
155 constant CFG_SPICTRL_TWEN : integer := 0;
156 constant CFG_SPICTRL_MAXWLEN : integer := (0);
157 constant CFG_SPICTRL_SYNCRAM : integer := 0;
158 constant CFG_SPICTRL_FT : integer := 0;
159
160 -- GRLIB debugging
161 constant CFG_DUART : integer := 0;
162 end;
@@ -0,0 +1,350
1
2
3 library ieee;
4 use ieee.std_logic_1164.all;
5 USE IEEE.NUMERIC_STD.ALL;
6 library grlib;
7 use grlib.amba.all;
8 use grlib.stdlib.all;
9 use grlib.devices.all;
10 library techmap;
11 use techmap.gencomp.all;
12 use techmap.allclkgen.all;
13 library gaisler;
14 use gaisler.memctrl.all;
15 use gaisler.leon3.all;
16 use gaisler.uart.all;
17 use gaisler.misc.all;
18 --pragma translate_off
19 use gaisler.sim.all;
20 --pragma translate_on
21 library opencores;
22 use opencores.spwpkg.all;
23 use opencores.spwambapkg.all;
24
25 use work.config.all;
26
27 library unisim;
28 use unisim.vcomponents.all;
29
30 entity leon3mp is
31 generic (
32 fabtech : integer := CFG_FABTECH;
33 memtech : integer := CFG_MEMTECH;
34 padtech : integer := CFG_PADTECH;
35 clktech : integer := CFG_CLKTECH;
36 disas : integer := CFG_DISAS; -- Enable disassembly to console
37 dbguart : integer := CFG_DUART; -- Print UART on console
38 pclow : integer := CFG_PCLOW
39 );
40 port (
41 CLK50 : in std_logic;
42 LEDS : inout std_logic_vector(7 downto 0);
43 SW : in std_logic_vector(4 downto 1);
44 dram_addr : out std_logic_vector(12 downto 0);
45 dram_ba_0 : out std_logic;
46 dram_ba_1 : out std_logic;
47 dram_dq : inout std_logic_vector(15 downto 0);
48
49 dram_clk : out std_logic;
50 dram_cke : out std_logic;
51 dram_cs_n : out std_logic;
52 dram_we_n : out std_logic; -- sdram write enable
53 dram_ras_n : out std_logic; -- sdram ras
54 dram_cas_n : out std_logic; -- sdram cas
55 dram_ldqm : out std_logic; -- sdram ldqm
56 dram_udqm : out std_logic; -- sdram udqm
57 uart_txd : out std_logic; -- DSU tx data
58 uart_rxd : in std_logic; -- DSU rx data
59
60 spw_rxdp : in std_logic;
61 spw_rxdn : in std_logic;
62 spw_rxsp : in std_logic;
63 spw_rxsn : in std_logic;
64 spw_txdp : out std_logic;
65 spw_txdn : out std_logic;
66 spw_txsp : out std_logic;
67 spw_txsn : out std_logic
68 );
69 end;
70
71 architecture rtl of leon3mp is
72 signal resetn : std_logic;
73 signal clkm, rstn, rstraw, rst : std_logic;
74 signal clkm_inv : std_logic := '0';
75
76 signal cptr : std_logic_vector(29 downto 0);
77 constant BOARD_FREQ : integer := 25000; -- CLK input frequency in KHz
78 constant CPU_FREQ : integer := BOARD_FREQ * CFG_CLKMUL / CFG_CLKDIV; -- cpu frequency in KHz
79 signal sdi : sdctrl_in_type;
80 signal sdo : sdctrl_out_type;
81
82 --AMBA bus standard interface signals--
83 signal apbi : apb_slv_in_type;
84 signal apbo : apb_slv_out_vector := (others => apb_none);
85 signal ahbsi : ahb_slv_in_type;
86 signal ahbso : ahb_slv_out_vector := (others => ahbs_none);
87 signal ahbmi : ahb_mst_in_type;
88 signal ahbmo : ahb_mst_out_vector := (others => ahbm_none);
89
90 signal cgi : clkgen_in_type;
91 signal cgo : clkgen_out_type;
92
93 signal dui : uart_in_type;
94 signal duo : uart_out_type;
95
96 signal irqi : irq_in_vector(0 to CFG_NCPU-1);
97 signal irqo : irq_out_vector(0 to CFG_NCPU-1);
98
99 signal dbgi : l3_debug_in_vector(0 to CFG_NCPU-1);
100 signal dbgo : l3_debug_out_vector(0 to CFG_NCPU-1);
101
102 signal dsui : dsu_in_type;
103 signal dsuo : dsu_out_type;
104
105
106 signal gpti : gptimer_in_type;
107 signal gpto : gptimer_out_type;
108
109 signal gpioi_0 : gpio_in_type;
110 signal gpioo_0 : gpio_out_type;
111
112 signal dsubren : std_logic :='0';
113
114 signal spw_di: std_logic;
115 signal spw_si: std_logic;
116 signal spw_do: std_logic;
117 signal spw_so: std_logic;
118 signal spw_tick_in: std_logic;
119
120 component sdctrl16
121 generic (
122 hindex : integer := 0;
123 haddr : integer := 0;
124 hmask : integer := 16#f00#;
125 ioaddr : integer := 16#000#;
126 iomask : integer := 16#fff#;
127 wprot : integer := 0;
128 invclk : integer := 0;
129 fast : integer := 0;
130 pwron : integer := 0;
131 sdbits : integer := 16;
132 oepol : integer := 0;
133 pageburst : integer := 0;
134 mobile : integer := 0
135 );
136 port (
137 rst : in std_ulogic;
138 clk : in std_ulogic;
139 ahbsi : in ahb_slv_in_type;
140 ahbso : out ahb_slv_out_type;
141 sdi : in sdctrl_in_type;
142 sdo : out sdctrl_out_type
143 );
144 end component;
145
146 begin
147 resetn <= SW(1);
148
149 clk_pad : clkpad generic map (tech => padtech) port map (CLK50, clkm);
150 clkm_inv <= not clkm;
151
152 resetn_pad : inpad generic map (tech => padtech) port map (resetn, rst);
153 rst0 : rstgen -- reset generator (reset is active LOW)
154 port map (rst, clkm, '1', rstn, rstraw);
155
156
157 ----------------------------------------------------------------------
158 --- AHB CONTROLLER --------------------------------------------------
159 ----------------------------------------------------------------------
160
161 ahb0 : ahbctrl -- AHB arbiter/multiplexer
162 generic map (defmast => CFG_DEFMST, split => CFG_SPLIT,
163 rrobin => CFG_RROBIN, ioaddr => CFG_AHBIO,
164 nahbm => CFG_NCPU+CFG_AHB_UART+1, nahbs => 8)
165
166 port map (rstn, clkm, ahbmi, ahbmo, ahbsi, ahbso);
167
168 ----------------------------------------------------------------------
169 ----- LEON3 processor and DSU ---------------------------------------
170 ----------------------------------------------------------------------
171
172 cpu : for i in 0 to CFG_NCPU-1 generate
173 nosh : if CFG_GRFPUSH = 0 generate
174 u0 : leon3s -- LEON3 processor
175 generic map (i, fabtech, memtech, CFG_NWIN, CFG_DSU, CFG_FPU*(1-CFG_GRFPUSH), CFG_V8,
176 0, CFG_MAC, pclow, CFG_NOTAG, CFG_NWP, CFG_ICEN, CFG_IREPL, CFG_ISETS, CFG_ILINE,
177 CFG_ISETSZ, CFG_ILOCK, CFG_DCEN, CFG_DREPL, CFG_DSETS, CFG_DLINE, CFG_DSETSZ,
178 CFG_DLOCK, CFG_DSNOOP, CFG_ILRAMEN, CFG_ILRAMSZ, CFG_ILRAMADDR, CFG_DLRAMEN,
179 CFG_DLRAMSZ, CFG_DLRAMADDR, CFG_MMUEN, CFG_ITLBNUM, CFG_DTLBNUM, CFG_TLB_TYPE, CFG_TLB_REP,
180 CFG_LDDEL, disas, CFG_ITBSZ, CFG_PWD, CFG_SVT, CFG_RSTADDR, CFG_NCPU-1,
181 0, 0, CFG_MMU_PAGE, CFG_BP, CFG_NP_ASI, CFG_WRPSR)
182 port map (clkm, rstn, ahbmi, ahbmo(i), ahbsi, ahbso,
183 irqi(i), irqo(i), dbgi(i), dbgo(i));
184 end generate;
185 end generate;
186
187 --ledr[0] lit when leon 3 debugvector signals error
188 dsugen : if CFG_DSU = 1 generate
189 dsu0 : dsu3 -- LEON3 Debug Support Unit (slave)
190 generic map (hindex => 2, haddr => 16#900#, hmask => 16#F00#,
191 ncpu => CFG_NCPU, tbits => 30, tech => memtech, irq => 0, kbytes => CFG_ATBSZ)
192 port map (rstn, clkm, ahbmi, ahbsi, ahbso(2), dbgo, dbgi, dsui, dsuo);
193 dsui.enable <= '1';
194
195 end generate;
196 nodsu : if CFG_DSU = 0 generate
197 ahbso(2) <= ahbs_none; dsuo.tstop <= '0'; dsuo.active <= '0'; --no timer freeze, no light.
198 end generate;
199
200 dcomgen : if CFG_AHB_UART = 1 generate
201 dcom0: ahbuart -- Debug UART
202 generic map (hindex => CFG_NCPU, pindex => 7, paddr => 7)
203 port map (rstn, clkm, dui, duo, apbi, apbo(7), ahbmi, ahbmo(CFG_NCPU));
204 end generate;
205 uart_txd <= duo.txd;
206 dui.rxd <= uart_rxd;
207
208
209 ----------------------------------------------------------------------
210 --- Memory controllers ----------------------------------------------
211 ----------------------------------------------------------------------
212
213
214 sdc : sdctrl16 generic map (hindex => 3, haddr => 16#400#, hmask => 16#FE0#, -- hmask => 16#C00#,
215 ioaddr => 1, fast => 0, pwron => 0, invclk => 0,
216 sdbits => 16, pageburst => 2)
217 port map (rstn, clkm, ahbsi, ahbso(3), sdi, sdo);
218 sa_pad : outpadv generic map (width => 13, tech => padtech)
219 port map (dram_addr, sdo.address(14 downto 2));
220 ba0_pad : outpad generic map (tech => padtech)
221 port map (dram_ba_0, sdo.address(15));
222 ba1_pad : outpad generic map (tech => padtech)
223 port map (dram_ba_1, sdo.address(16));
224 sd_pad : iopadvv generic map (width => 16, tech => padtech)
225 port map (dram_dq(15 downto 0), sdo.data(15 downto 0), sdo.vbdrive(15 downto 0), sdi.data(15 downto 0));
226 sdcke_pad : outpad generic map (tech => padtech)
227 port map (dram_cke, sdo.sdcke(0));
228 sdwen_pad : outpad generic map (tech => padtech)
229 port map (dram_we_n, sdo.sdwen);
230 sdcsn_pad : outpad generic map (tech => padtech)
231 port map (dram_cs_n, sdo.sdcsn(0));
232 sdras_pad : outpad generic map (tech => padtech)
233 port map (dram_ras_n, sdo.rasn);
234 sdcas_pad : outpad generic map (tech => padtech)
235 port map (dram_cas_n, sdo.casn);
236 sdldqm_pad : outpad generic map (tech => padtech)
237 port map (dram_ldqm, sdo.dqm(0) );
238 sdudqm_pad : outpad generic map (tech => padtech)
239 port map (dram_udqm, sdo.dqm(1));
240 dram_clk_pad : outpad generic map (tech => padtech)
241 port map (dram_clk, clkm_inv);
242
243 ----------------------------------------------------------------------
244 --- APB Bridge and various periherals -------------------------------
245 ----------------------------------------------------------------------
246
247 apb0 : apbctrl -- AHB/APB bridge
248 generic map (hindex => 1, haddr => CFG_APBADDR)
249 port map (rstn, clkm, ahbsi, ahbso(1), apbi, apbo );
250
251 ----------------------------------------------------------------------------------------
252
253 irqctrl : if CFG_IRQ3_ENABLE /= 0 generate
254 irqctrl0 : irqmp -- interrupt controller
255 generic map (pindex => 2, paddr => 2, ncpu => CFG_NCPU)
256 port map (rstn, clkm, apbi, apbo(2), irqo, irqi);
257 end generate;
258 irq3 : if CFG_IRQ3_ENABLE = 0 generate
259 x : for i in 0 to CFG_NCPU-1 generate irqi(i).irl <= "0000"; end generate;
260 apbo(2) <= apb_none;
261 end generate;
262
263 --Timer unit, generates interrupts when a timer underflow.
264 gpt : if CFG_GPT_ENABLE /= 0 generate
265 timer0 : gptimer -- timer unit
266 generic map (pindex => 3, paddr => 3, pirq => CFG_GPT_IRQ,
267 sepirq => CFG_GPT_SEPIRQ, sbits => CFG_GPT_SW, ntimers => CFG_GPT_NTIM,
268 nbits => CFG_GPT_TW)
269 port map (rstn, clkm, apbi, apbo(3), gpti, gpto);
270 gpti <= gpti_dhalt_drive(dsuo.tstop);
271 end generate;
272 notim : if CFG_GPT_ENABLE = 0 generate apbo(3) <= apb_none; end generate;
273
274 gpio0 : if CFG_GRGPIO_ENABLE /= 0 generate -- GR GPIO0 unit
275 grgpio0: grgpio
276 generic map( pindex => 9, paddr => 9, imask => CFG_GRGPIO_IMASK, nbits => 8)
277 port map( rstn, clkm, apbi, apbo(9), gpioi_0, gpioo_0);
278 pio_pads : for i in 0 to 7 generate
279 pio_pad : iopad generic map (tech => padtech)
280 port map (LEDS(i), gpioo_0.dout(i), gpioo_0.oen(i), gpioi_0.din(i));
281 end generate;
282 end generate;
283 nogpio0: if CFG_GRGPIO_ENABLE = 0 generate apbo(9) <= apb_none; end generate;
284
285
286 -----------------------------------------------------------------------
287 --- SpaceWire Light --------------------------------------------------
288 -----------------------------------------------------------------------
289
290 spw0: spwamba
291 generic map (
292 tech => memtech,
293 hindex => 2,
294 pindex => 10,
295 paddr => 10,
296 pirq => 10,
297 sysfreq => 50.0e6,
298 txclkfreq => 10.0e6,
299 rximpl => impl_generic,
300 rxchunk => 1,
301 tximpl => impl_generic,
302 timecodegen => true,
303 rxfifosize => 11,
304 txfifosize => 11,
305 desctablesize => 10,
306 maxburst => 3 )
307 port map (
308 clk => clkm,
309 rxclk => clkm,
310 txclk => clkm,
311 rstn => rstn,
312 apbi => apbi,
313 apbo => apbo(10),
314 ahbi => ahbmi,
315 ahbo => ahbmo(2),
316 tick_in => spw_tick_in,
317 tick_out => open,
318 spw_di => spw_di,
319 spw_si => spw_si,
320 spw_do => spw_do,
321 spw_so => spw_so );
322
323 spw_tick_in <= gpto.tick(2) when CFG_GPT_ENABLE /= 0 else '0';
324
325 spw_rxd_pad: inpad_ds
326 generic map (padtech, lvds, x33v)
327 port map (spw_rxdp, spw_rxdn, spw_di);
328 spw_rxs_pad: inpad_ds
329 generic map (padtech, lvds, x33v)
330 port map (spw_rxsp, spw_rxsn, spw_si);
331 -- spw_txd_pad: outpad_ds
332 -- generic map (padtech, lvds, x33v)
333 -- port map (spw_txdp, spw_txdn, spw_do, '0');
334 -- spw_txs_pad: outpad_ds
335 -- generic map (padtech, lvds, x33v)
336 -- port map (spw_txsp, spw_txsn, spw_so, '0');
337
338
339 spw_txdp_pad : outpad generic map (tech => padtech)
340 port map (spw_txdp, spw_do);
341 spw_txdn_pad : outpad generic map (tech => padtech)
342 port map (spw_txdn, not spw_do);
343
344 spw_txsp_pad : outpad generic map (tech => padtech)
345 port map (spw_txsp, spw_so);
346 spw_txsn_pad : outpad generic map (tech => padtech)
347 port map (spw_txsn, not spw_so);
348
349 end rtl;
350
@@ -0,0 +1,4
1
2 NET CLK50 PERIOD = 20.0 ;
3
4
This diff has been collapsed as it changes many lines, (1550 lines changed) Show them Hide them
@@ -0,0 +1,1550
1
2 --*****************************************************************************
3 --
4 -- Micron Semiconductor Products, Inc.
5 --
6 -- Copyright 1997, Micron Semiconductor Products, Inc.
7 -- All rights reserved.
8 --
9 --*****************************************************************************
10
11 -- pragma translate_off
12
13 library ieee;
14 use ieee.std_logic_1164.ALL;
15 use std.textio.all;
16
17 PACKAGE mti_pkg IS
18
19 FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC;
20 FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER;
21 FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER;
22 FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER;
23 PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR);
24
25
26 END mti_pkg;
27
28 PACKAGE BODY mti_pkg IS
29
30 -- Convert BIT to STD_LOGIC
31 FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC IS
32 BEGIN
33 CASE s IS
34 WHEN '0' => RETURN ('0');
35 WHEN '1' => RETURN ('1');
36 WHEN OTHERS => RETURN ('0');
37 END CASE;
38 END;
39
40 -- Convert STD_LOGIC to INTEGER
41 FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS
42 VARIABLE result : INTEGER := 0;
43 VARIABLE weight : INTEGER := 1;
44 BEGIN
45 IF input = '1' THEN
46 result := weight;
47 ELSE
48 result := 0; -- if unknowns, default to logic 0
49 END IF;
50 RETURN result;
51 END TO_INTEGER;
52
53 -- Convert BIT_VECTOR to INTEGER
54 FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS
55 VARIABLE result : INTEGER := 0;
56 VARIABLE weight : INTEGER := 1;
57 BEGIN
58 FOR i IN input'LOW TO input'HIGH LOOP
59 IF input(i) = '1' THEN
60 result := result + weight;
61 ELSE
62 result := result + 0; -- if unknowns, default to logic 0
63 END IF;
64 weight := weight * 2;
65 END LOOP;
66 RETURN result;
67 END TO_INTEGER;
68
69 -- Convert STD_LOGIC_VECTOR to INTEGER
70 FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS
71 VARIABLE result : INTEGER := 0;
72 VARIABLE weight : INTEGER := 1;
73 BEGIN
74 FOR i IN input'LOW TO input'HIGH LOOP
75 IF input(i) = '1' THEN
76 result := result + weight;
77 ELSE
78 result := result + 0; -- if unknowns, default to logic 0
79 END IF;
80 weight := weight * 2;
81 END LOOP;
82 RETURN result;
83 END TO_INTEGER;
84
85 -- Conver INTEGER to BIT_VECTOR
86 PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS
87 VARIABLE work,offset,outputlen,j : INTEGER := 0;
88 BEGIN
89 --length of vector
90 IF output'LENGTH > 32 THEN --'
91 outputlen := 32;
92 offset := output'LENGTH - 32; --'
93 IF input >= 0 THEN
94 FOR i IN offset-1 DOWNTO 0 LOOP
95 output(output'HIGH - i) := '0'; --'
96 END LOOP;
97 ELSE
98 FOR i IN offset-1 DOWNTO 0 LOOP
99 output(output'HIGH - i) := '1'; --'
100 END LOOP;
101 END IF;
102 ELSE
103 outputlen := output'LENGTH; --'
104 END IF;
105 --positive value
106 IF (input >= 0) THEN
107 work := input;
108 j := outputlen - 1;
109 FOR i IN 1 to 32 LOOP
110 IF j >= 0 then
111 IF (work MOD 2) = 0 THEN
112 output(output'HIGH-j-offset) := '0'; --'
113 ELSE
114 output(output'HIGH-j-offset) := '1'; --'
115 END IF;
116 END IF;
117 work := work / 2;
118 j := j - 1;
119 END LOOP;
120 IF outputlen = 32 THEN
121 output(output'HIGH) := '0'; --'
122 END IF;
123 --negative value
124 ELSE
125 work := (-input) - 1;
126 j := outputlen - 1;
127 FOR i IN 1 TO 32 LOOP
128 IF j>= 0 THEN
129 IF (work MOD 2) = 0 THEN
130 output(output'HIGH-j-offset) := '1'; --'
131 ELSE
132 output(output'HIGH-j-offset) := '0'; --'
133 END IF;
134 END IF;
135 work := work / 2;
136 j := j - 1;
137 END LOOP;
138 IF outputlen = 32 THEN
139 output(output'HIGH) := '1'; --'
140 END IF;
141 END IF;
142 END TO_BITVECTOR;
143
144 END mti_pkg;
145
146 -----------------------------------------------------------------------------------------
147 --
148 -- File Name: MT48LC16M16A2.VHD
149 -- Version: 0.0g
150 -- Date: June 29th, 2000
151 -- Model: Behavioral
152 -- Simulator: Model Technology (PC version 5.3 PE)
153 --
154 -- Dependencies: None
155 --
156 -- Author: Son P. Huynh
157 -- Email: sphuynh@micron.com
158 -- Phone: (208) 368-3825
159 -- Company: Micron Technology, Inc.
160 -- Part Number: MT48LC16M16A2 (4Mb x 16 x 4 Banks)
161 --
162 -- Description: Micron 256Mb SDRAM
163 --
164 -- Limitation: - Doesn't check for 4096-cycle refresh --'
165 --
166 -- Note: - Set simulator resolution to "ps" accuracy
167 --
168 -- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
169 -- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
170 -- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
171 -- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
172 --
173 -- Copyright (c) 1998 Micron Semiconductor Products, Inc.
174 -- All rights researved
175 --
176 -- Rev Author Phone Date Changes
177 -- ---- ---------------------------- ---------- -------------------------------------
178 -- 0.0g Son Huynh 208-368-3825 06/29/2000 Add Load/Dump memory array
179 -- Micron Technology Inc. Modify tWR + tRAS timing check
180 --
181 -- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto)
182 -- Micron Technology Inc. Fix tWR = 15 ns (Manual)
183 -- Fix tRP (Autoprecharge to AutoRefresh)
184 --
185 -- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP
186 -- Micron Technology Inc. Fix tRC check in Load Mode Register
187 --
188 -- 0.0b Son P. Huynh 208-368-3825 01/06/1998 Derive from 64Mb SDRAM model
189 -- Micron Technology Inc.
190 --
191 -----------------------------------------------------------------------------------------
192
193 LIBRARY STD;
194 USE STD.TEXTIO.ALL;
195 LIBRARY IEEE;
196 USE IEEE.STD_LOGIC_1164.ALL;
197 LIBRARY WORK;
198 USE WORK.MTI_PKG.ALL;
199 use std.textio.all;
200
201 library grlib;
202 use grlib.stdlib.all;
203 use grlib.stdio.all;
204
205 ENTITY mt48lc16m16a2 IS
206 GENERIC (
207 -- Timing Parameters for -75 (PC133) and CAS Latency = 2
208 tAC : TIME := 6.0 ns;
209 tHZ : TIME := 7.0 ns;
210 tOH : TIME := 2.7 ns;
211 tMRD : INTEGER := 2; -- 2 Clk Cycles
212 tRAS : TIME := 44.0 ns;
213 tRC : TIME := 66.0 ns;
214 tRCD : TIME := 20.0 ns;
215 tRP : TIME := 20.0 ns;
216 tRRD : TIME := 15.0 ns;
217 tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
218 tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns)
219
220 tAH : TIME := 0.8 ns;
221 tAS : TIME := 1.5 ns;
222 tCH : TIME := 2.5 ns;
223 tCL : TIME := 2.5 ns;
224 tCK : TIME := 10.0 ns;
225 tDH : TIME := 0.8 ns;
226 tDS : TIME := 1.5 ns;
227 tCKH : TIME := 0.8 ns;
228 tCKS : TIME := 1.5 ns;
229 tCMH : TIME := 0.8 ns;
230 tCMS : TIME := 1.5 ns;
231
232 addr_bits : INTEGER := 13;
233 data_bits : INTEGER := 16;
234 col_bits : INTEGER := 9;
235 index : INTEGER := 0;
236 fname : string := "ram.srec" -- File to read from
237 );
238 PORT (
239 Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
240 Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
241 Ba : IN STD_LOGIC_VECTOR := "00";
242 Clk : IN STD_LOGIC := '0';
243 Cke : IN STD_LOGIC := '1';
244 Cs_n : IN STD_LOGIC := '1';
245 Ras_n : IN STD_LOGIC := '1';
246 Cas_n : IN STD_LOGIC := '1';
247 We_n : IN STD_LOGIC := '1';
248 Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"
249 );
250 END mt48lc16m16a2;
251
252 ARCHITECTURE behave OF mt48lc16m16a2 IS
253 TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, LOAD_FILE, DUMP_FILE);
254 TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER;
255 TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME;
256 TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT;
257 TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0);
258 TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0);
259 TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State;
260 SIGNAL Operation : State := NOP;
261 SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
262 SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0';
263 SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0';
264 SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0';
265 SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0';
266 SIGNAL Ras_in, Cas_in, We_in : BIT := '0';
267 SIGNAL Write_burst_mode : BIT := '0';
268 SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0';
269
270 -- Checking internal wires
271 SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000";
272 SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000";
273 SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0';
274 SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00";
275 SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
276 SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
277
278 BEGIN
279 -- CS# Decode
280 WITH Cs_n SELECT
281 Cas_in <= TO_BIT (Cas_n, '1') WHEN '0',
282 '1' WHEN '1',
283 '1' WHEN OTHERS;
284 WITH Cs_n SELECT
285 Ras_in <= TO_BIT (Ras_n, '1') WHEN '0',
286 '1' WHEN '1',
287 '1' WHEN OTHERS;
288 WITH Cs_n SELECT
289 We_in <= TO_BIT (We_n, '1') WHEN '0',
290 '1' WHEN '1',
291 '1' WHEN OTHERS;
292
293 -- Commands Decode
294 Active_enable <= NOT(Ras_in) AND Cas_in AND We_in;
295 Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in;
296 Burst_term <= Ras_in AND Cas_in AND NOT(We_in);
297 Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in);
298 Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in);
299 Read_enable <= Ras_in AND NOT(Cas_in) AND We_in;
300 Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in);
301
302 -- Burst Length Decode
303 Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0));
304 Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0);
305 Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0));
306 Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
307
308 -- CAS Latency Decode
309 Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4));
310 Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4);
311
312 -- Write Burst Mode
313 Write_burst_mode <= Mode_reg(9);
314
315 -- RAS Clock for checking tWR and tRP
316 PROCESS
317 variable Clk0, Clk1 : integer := 0;
318 begin
319 RAS_clk <= '1';
320 wait for 0.5 ns;
321 RAS_clk <= '0';
322 wait for 0.5 ns;
323 if Clk0 > 100 or Clk1 > 100 then
324 wait;
325 else
326 if Clk = '1' and Cke = '1' then
327 Clk0 := 0;
328 Clk1 := Clk1 + 1;
329 elsif Clk = '0' and Cke = '1' then
330 Clk0 := Clk0 + 1;
331 Clk1 := 0;
332 end if;
333 end if;
334 END PROCESS;
335
336 -- System Clock
337 int_clk : PROCESS (Clk)
338 begin
339 IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN --'
340 CkeZ <= TO_BIT(Cke, '1');
341 END IF;
342 Sys_clk <= CkeZ AND TO_BIT(Clk, '0');
343 END PROCESS;
344
345 state_register : PROCESS
346 -- NOTE: The extra bits in RAM_TYPE is for checking memory access. A logic 1 means
347 -- the location is in use. This will be checked when doing memory DUMP.
348 TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits DOWNTO 0);
349 TYPE ram_pntr IS ACCESS ram_type;
350 TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr;
351 VARIABLE Bank0 : ram_stor;
352 VARIABLE Bank1 : ram_stor;
353 VARIABLE Bank2 : ram_stor;
354 VARIABLE Bank3 : ram_stor;
355 VARIABLE Row_index, Col_index : INTEGER := 0;
356 VARIABLE Dq_temp : BIT_VECTOR (data_bits DOWNTO 0) := (OTHERS => '0');
357
358 VARIABLE Col_addr : Array4xCBV;
359 VARIABLE Bank_addr : Array4x2BV;
360 VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00";
361
362 VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00";
363 VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
364 VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
365 VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
366 VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
367 VARIABLE Burst_counter : INTEGER := 0;
368
369 VARIABLE Command : Array_state;
370 VARIABLE Bank_precharge : Array4x2BV;
371 VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0');
372 VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0');
373 VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0');
374 VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0');
375 VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0');
376 VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0');
377 VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00";
378 VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
379 VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0);
380
381 VARIABLE Data_in_enable, Data_out_enable : BIT := '0';
382 VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0';
383 VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0';
384
385 -- Timing Check
386 VARIABLE MRD_chk : INTEGER := 0;
387 VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0);
388 VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
389 VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
390 VARIABLE RC_chk, RRD_chk : TIME := 0 ns;
391 VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns;
392 VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns;
393 VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns;
394
395 -- Load and Dumb variables
396 FILE file_load : TEXT open read_mode is fname; -- Data load
397 FILE file_dump : TEXT open write_mode is "dumpdata.txt"; -- Data dump
398 VARIABLE bank_load : bit_vector ( 1 DOWNTO 0);
399 VARIABLE rows_load : BIT_VECTOR (12 DOWNTO 0);
400 VARIABLE cols_load : BIT_VECTOR ( 8 DOWNTO 0);
401 VARIABLE data_load : BIT_VECTOR (15 DOWNTO 0);
402 VARIABLE i, j : INTEGER;
403 VARIABLE good_load : BOOLEAN;
404 VARIABLE l : LINE;
405 variable load : std_logic := '1';
406 variable dump : std_logic := '0';
407 variable ch : character;
408 variable rectype : bit_vector(3 downto 0);
409 variable recaddr : bit_vector(31 downto 0);
410 variable reclen : bit_vector(7 downto 0);
411 variable recdata : bit_vector(0 to 16*8-1);
412
413 -- Initialize empty rows
414 PROCEDURE Init_mem (Bank : bit_vector (1 DOWNTO 0); Row_index : INTEGER) IS
415 VARIABLE i, j : INTEGER := 0;
416 BEGIN
417 IF Bank = "00" THEN
418 IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty
419 Bank0 (Row_index) := NEW ram_type; -- Open new row for access
420 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros
421 FOR j IN (data_bits) DOWNTO 0 LOOP
422 Bank0 (Row_index) (i) (j) := '0';
423 END LOOP;
424 END LOOP;
425 END IF;
426 ELSIF Bank = "01" THEN
427 IF Bank1 (Row_index) = NULL THEN
428 Bank1 (Row_index) := NEW ram_type;
429 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
430 FOR j IN (data_bits) DOWNTO 0 LOOP
431 Bank1 (Row_index) (i) (j) := '0';
432 END LOOP;
433 END LOOP;
434 END IF;
435 ELSIF Bank = "10" THEN
436 IF Bank2 (Row_index) = NULL THEN
437 Bank2 (Row_index) := NEW ram_type;
438 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
439 FOR j IN (data_bits) DOWNTO 0 LOOP
440 Bank2 (Row_index) (i) (j) := '0';
441 END LOOP;
442 END LOOP;
443 END IF;
444 ELSIF Bank = "11" THEN
445 IF Bank3 (Row_index) = NULL THEN
446 Bank3 (Row_index) := NEW ram_type;
447 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
448 FOR j IN (data_bits) DOWNTO 0 LOOP
449 Bank3 (Row_index) (i) (j) := '0';
450 END LOOP;
451 END LOOP;
452 END IF;
453 END IF;
454 END;
455
456 -- Burst Counter
457 PROCEDURE Burst_decode IS
458 VARIABLE Col_int : INTEGER := 0;
459 VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
460 BEGIN
461 -- Advance Burst Counter
462 Burst_counter := Burst_counter + 1;
463
464 -- Burst Type
465 IF Mode_reg (3) = '0' THEN
466 Col_int := TO_INTEGER(Col);
467 Col_int := Col_int + 1;
468 TO_BITVECTOR (Col_int, Col_temp);
469 ELSIF Mode_reg (3) = '1' THEN
470 TO_BITVECTOR (Burst_counter, Col_vec);
471 Col_temp (2) := Col_vec (2) XOR Col_brst (2);
472 Col_temp (1) := Col_vec (1) XOR Col_brst (1);
473 Col_temp (0) := Col_vec (0) XOR Col_brst (0);
474 END IF;
475
476 -- Burst Length
477 IF Burst_length_2 = '1' THEN
478 Col (0) := Col_temp (0);
479 ELSIF Burst_length_4 = '1' THEN
480 Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0);
481 ELSIF Burst_length_8 = '1' THEN
482 Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0);
483 ELSE
484 Col := Col_temp;
485 END IF;
486
487 -- Burst Read Single Write
488 IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN
489 Data_in_enable := '0';
490 END IF;
491
492 -- Data counter
493 IF Burst_length_1 = '1' THEN
494 IF Burst_counter >= 1 THEN
495 IF Data_in_enable = '1' THEN
496 Data_in_enable := '0';
497 ELSIF Data_out_enable = '1' THEN
498 Data_out_enable := '0';
499 END IF;
500 END IF;
501 ELSIF Burst_length_2 = '1' THEN
502 IF Burst_counter >= 2 THEN
503 IF Data_in_enable = '1' THEN
504 Data_in_enable := '0';
505 ELSIF Data_out_enable = '1' THEN
506 Data_out_enable := '0';
507 END IF;
508 END IF;
509 ELSIF Burst_length_4 = '1' THEN
510 IF Burst_counter >= 4 THEN
511 IF Data_in_enable = '1' THEN
512 Data_in_enable := '0';
513 ELSIF Data_out_enable = '1' THEN
514 Data_out_enable := '0';
515 END IF;
516 END IF;
517 ELSIF Burst_length_8 = '1' THEN
518 IF Burst_counter >= 8 THEN
519 IF Data_in_enable = '1' THEN
520 Data_in_enable := '0';
521 ELSIF Data_out_enable = '1' THEN
522 Data_out_enable := '0';
523 END IF;
524 END IF;
525 END IF;
526 END;
527
528 BEGIN
529 WAIT ON Sys_clk, RAS_clk;
530 IF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '0' THEN --'
531 -- Internal Command Pipeline
532 Command(0) := Command(1);
533 Command(1) := Command(2);
534 Command(2) := Command(3);
535 Command(3) := NOP;
536
537 Col_addr(0) := Col_addr(1);
538 Col_addr(1) := Col_addr(2);
539 Col_addr(2) := Col_addr(3);
540 Col_addr(3) := (OTHERS => '0');
541
542 Bank_addr(0) := Bank_addr(1);
543 Bank_addr(1) := Bank_addr(2);
544 Bank_addr(2) := Bank_addr(3);
545 Bank_addr(3) := "00";
546
547 Bank_precharge(0) := Bank_precharge(1);
548 Bank_precharge(1) := Bank_precharge(2);
549 Bank_precharge(2) := Bank_precharge(3);
550 Bank_precharge(3) := "00";
551
552 A10_precharge(0) := A10_precharge(1);
553 A10_precharge(1) := A10_precharge(2);
554 A10_precharge(2) := A10_precharge(3);
555 A10_precharge(3) := '0';
556
557 -- Operation Decode (Optional for showing current command on posedge clock / debug feature)
558 IF Active_enable = '1' THEN
559 Operation <= ACT;
560 ELSIF Aref_enable = '1' THEN
561 Operation <= A_REF;
562 ELSIF Burst_term = '1' THEN
563 Operation <= BST;
564 ELSIF Mode_reg_enable = '1' THEN
565 Operation <= LMR;
566 ELSIF Prech_enable = '1' THEN
567 Operation <= PRECH;
568 ELSIF Read_enable = '1' THEN
569 IF Addr(10) = '0' THEN
570 Operation <= READ;
571 ELSE
572 Operation <= READ_A;
573 END IF;
574 ELSIF Write_enable = '1' THEN
575 IF Addr(10) = '0' THEN
576 Operation <= WRITE;
577 ELSE
578 Operation <= WRITE_A;
579 END IF;
580 ELSE
581 Operation <= NOP;
582 END IF;
583
584 -- Dqm pipeline for Read
585 Dqm_reg0 := Dqm_reg1;
586 Dqm_reg1 := TO_BITVECTOR(Dqm);
587
588 -- Read or Write with Auto Precharge Counter
589 IF Auto_precharge (0) = '1' THEN
590 Count_precharge (0) := Count_precharge (0) + 1;
591 END IF;
592 IF Auto_precharge (1) = '1' THEN
593 Count_precharge (1) := Count_precharge (1) + 1;
594 END IF;
595 IF Auto_precharge (2) = '1' THEN
596 Count_precharge (2) := Count_precharge (2) + 1;
597 END IF;
598 IF Auto_precharge (3) = '1' THEN
599 Count_precharge (3) := Count_precharge (3) + 1;
600 END IF;
601
602 -- Auto Precharge Timer for tWR
603 if (Burst_length_1 = '1' OR Write_burst_mode = '1') then
604 if (Count_precharge(0) = 1) then
605 Count_time(0) := NOW;
606 end if;
607 if (Count_precharge(1) = 1) then
608 Count_time(1) := NOW;
609 end if;
610 if (Count_precharge(2) = 1) then
611 Count_time(2) := NOW;
612 end if;
613 if (Count_precharge(3) = 1) then
614 Count_time(3) := NOW;
615 end if;
616 elsif (Burst_length_2 = '1') then
617 if (Count_precharge(0) = 2) then
618 Count_time(0) := NOW;
619 end if;
620 if (Count_precharge(1) = 2) then
621 Count_time(1) := NOW;
622 end if;
623 if (Count_precharge(2) = 2) then
624 Count_time(2) := NOW;
625 end if;
626 if (Count_precharge(3) = 2) then
627 Count_time(3) := NOW;
628 end if;
629 elsif (Burst_length_4 = '1') then
630 if (Count_precharge(0) = 4) then
631 Count_time(0) := NOW;
632 end if;
633 if (Count_precharge(1) = 4) then
634 Count_time(1) := NOW;
635 end if;
636 if (Count_precharge(2) = 4) then
637 Count_time(2) := NOW;
638 end if;
639 if (Count_precharge(3) = 4) then
640 Count_time(3) := NOW;
641 end if;
642 elsif (Burst_length_8 = '1') then
643 if (Count_precharge(0) = 8) then
644 Count_time(0) := NOW;
645 end if;
646 if (Count_precharge(1) = 8) then
647 Count_time(1) := NOW;
648 end if;
649 if (Count_precharge(2) = 8) then
650 Count_time(2) := NOW;
651 end if;
652 if (Count_precharge(3) = 8) then
653 Count_time(3) := NOW;
654 end if;
655 end if;
656
657 -- tMRD Counter
658 MRD_chk := MRD_chk + 1;
659
660 -- tWR Counter
661 WR_counter(0) := WR_counter(0) + 1;
662 WR_counter(1) := WR_counter(1) + 1;
663 WR_counter(2) := WR_counter(2) + 1;
664 WR_counter(3) := WR_counter(3) + 1;
665
666
667 -- Auto Refresh
668 IF Aref_enable = '1' THEN
669 -- Auto Refresh to Auto Refresh
670 ASSERT (NOW - RC_chk >= tRC)
671 REPORT "tRC violation during Auto Refresh"
672 SEVERITY WARNING;
673 -- Precharge to Auto Refresh
674 ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP)
675 REPORT "tRP violation during Auto Refresh"
676 SEVERITY WARNING;
677 -- All banks must be idle before refresh
678 IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN
679 ASSERT (FALSE)
680 REPORT "All banks must be Precharge before Auto Refresh"
681 SEVERITY WARNING;
682 END IF;
683 -- Record current tRC time
684 RC_chk := NOW;
685 END IF;
686
687 -- Load Mode Register
688 IF Mode_reg_enable = '1' THEN
689 Mode_reg <= TO_BITVECTOR (Addr);
690 IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN
691 ASSERT (FALSE)
692 REPORT "All bank must be Precharge before Load Mode Register"
693 SEVERITY WARNING;
694 END IF;
695 -- REF to LMR
696 ASSERT (NOW - RC_chk >= tRC)
697 REPORT "tRC violation during Load Mode Register"
698 SEVERITY WARNING;
699 -- LMR to LMR
700 ASSERT (MRD_chk >= tMRD)
701 REPORT "tMRD violation during Load Mode Register"
702 SEVERITY WARNING;
703 -- Record current tMRD time
704 MRD_chk := 0;
705 END IF;
706
707 -- Active Block (latch Bank and Row Address)
708 IF Active_enable = '1' THEN
709 IF Ba = "00" AND Pc_b0 = '1' THEN
710 Act_b0 := '1';
711 Pc_b0 := '0';
712 B0_row_addr := TO_BITVECTOR (Addr);
713 RCD_chk0 := NOW;
714 RAS_chk0 := NOW;
715 -- Precharge to Active Bank 0
716 ASSERT (NOW - RP_chk0 >= tRP)
717 REPORT "tRP violation during Activate Bank 0"
718 SEVERITY WARNING;
719 ELSIF Ba = "01" AND Pc_b1 = '1' THEN
720 Act_b1 := '1';
721 Pc_b1 := '0';
722 B1_row_addr := TO_BITVECTOR (Addr);
723 RCD_chk1 := NOW;
724 RAS_chk1 := NOW;
725 -- Precharge to Active Bank 1
726 ASSERT (NOW - RP_chk1 >= tRP)
727 REPORT "tRP violation during Activate Bank 1"
728 SEVERITY WARNING;
729 ELSIF Ba = "10" AND Pc_b2 = '1' THEN
730 Act_b2 := '1';
731 Pc_b2 := '0';
732 B2_row_addr := TO_BITVECTOR (Addr);
733 RCD_chk2 := NOW;
734 RAS_chk2 := NOW;
735 -- Precharge to Active Bank 2
736 ASSERT (NOW - RP_chk2 >= tRP)
737 REPORT "tRP violation during Activate Bank 2"
738 SEVERITY WARNING;
739 ELSIF Ba = "11" AND Pc_b3 = '1' THEN
740 Act_b3 := '1';
741 Pc_b3 := '0';
742 B3_row_addr := TO_BITVECTOR (Addr);
743 RCD_chk3 := NOW;
744 RAS_chk3 := NOW;
745 -- Precharge to Active Bank 3
746 ASSERT (NOW - RP_chk3 >= tRP)
747 REPORT "tRP violation during Activate Bank 3"
748 SEVERITY WARNING;
749 ELSIF Ba = "00" AND Pc_b0 = '0' THEN
750 ASSERT (FALSE)
751 REPORT "Bank 0 is not Precharged"
752 SEVERITY WARNING;
753 ELSIF Ba = "01" AND Pc_b1 = '0' THEN
754 ASSERT (FALSE)
755 REPORT "Bank 1 is not Precharged"
756 SEVERITY WARNING;
757 ELSIF Ba = "10" AND Pc_b2 = '0' THEN
758 ASSERT (FALSE)
759 REPORT "Bank 2 is not Precharged"
760 SEVERITY WARNING;
761 ELSIF Ba = "11" AND Pc_b3 = '0' THEN
762 ASSERT (FALSE)
763 REPORT "Bank 3 is not Precharged"
764 SEVERITY WARNING;
765 END IF;
766 -- Active Bank A to Active Bank B
767 IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN
768 ASSERT (FALSE)
769 REPORT "tRRD violation during Activate"
770 SEVERITY WARNING;
771 END IF;
772 -- LMR to ACT
773 ASSERT (MRD_chk >= tMRD)
774 REPORT "tMRD violation during Activate"
775 SEVERITY WARNING;
776 -- AutoRefresh to Activate
777 ASSERT (NOW - RC_chk >= tRC)
778 REPORT "tRC violation during Activate"
779 SEVERITY WARNING;
780 -- Record variable for checking violation
781 RRD_chk := NOW;
782 Previous_bank := TO_BITVECTOR (Ba);
783 END IF;
784
785 -- Precharge Block
786 IF Prech_enable = '1' THEN
787 IF Addr(10) = '1' THEN
788 Pc_b0 := '1';
789 Pc_b1 := '1';
790 Pc_b2 := '1';
791 Pc_b3 := '1';
792 Act_b0 := '0';
793 Act_b1 := '0';
794 Act_b2 := '0';
795 Act_b3 := '0';
796 RP_chk0 := NOW;
797 RP_chk1 := NOW;
798 RP_chk2 := NOW;
799 RP_chk3 := NOW;
800 -- Activate to Precharge all banks
801 ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS))
802 REPORT "tRAS violation during Precharge all banks"
803 SEVERITY WARNING;
804 -- tWR violation check for Write
805 IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR
806 (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN
807 ASSERT (FALSE)
808 REPORT "tWR violation during Precharge ALL banks"
809 SEVERITY WARNING;
810 END IF;
811 ELSIF Addr(10) = '0' THEN
812 IF Ba = "00" THEN
813 Pc_b0 := '1';
814 Act_b0 := '0';
815 RP_chk0 := NOW;
816 -- Activate to Precharge bank 0
817 ASSERT (NOW - RAS_chk0 >= tRAS)
818 REPORT "tRAS violation during Precharge bank 0"
819 SEVERITY WARNING;
820 ELSIF Ba = "01" THEN
821 Pc_b1 := '1';
822 Act_b1 := '0';
823 RP_chk1 := NOW;
824 -- Activate to Precharge bank 1
825 ASSERT (NOW - RAS_chk1 >= tRAS)
826 REPORT "tRAS violation during Precharge bank 1"
827 SEVERITY WARNING;
828 ELSIF Ba = "10" THEN
829 Pc_b2 := '1';
830 Act_b2 := '0';
831 RP_chk2 := NOW;
832 -- Activate to Precharge bank 2
833 ASSERT (NOW - RAS_chk2 >= tRAS)
834 REPORT "tRAS violation during Precharge bank 2"
835 SEVERITY WARNING;
836 ELSIF Ba = "11" THEN
837 Pc_b3 := '1';
838 Act_b3 := '0';
839 RP_chk3 := NOW;
840 -- Activate to Precharge bank 3
841 ASSERT (NOW - RAS_chk3 >= tRAS)
842 REPORT "tRAS violation during Precharge bank 3"
843 SEVERITY WARNING;
844 END IF;
845 -- tWR violation check for Write
846 ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp)
847 REPORT "tWR violation during Precharge"
848 SEVERITY WARNING;
849 END IF;
850 -- Terminate a Write Immediately (if same bank or all banks)
851 IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN
852 Data_in_enable := '0';
853 END IF;
854 -- Precharge Command Pipeline for READ
855 IF CAS_latency_3 = '1' THEN
856 Command(2) := PRECH;
857 Bank_precharge(2) := TO_BITVECTOR (Ba);
858 A10_precharge(2) := TO_BIT(Addr(10));
859 ELSIF CAS_latency_2 = '1' THEN
860 Command(1) := PRECH;
861 Bank_precharge(1) := TO_BITVECTOR (Ba);
862 A10_precharge(1) := TO_BIT(Addr(10));
863 END IF;
864 END IF;
865
866 -- Burst Terminate
867 IF Burst_term = '1' THEN
868 -- Terminate a Write immediately
869 IF Data_in_enable = '1' THEN
870 Data_in_enable := '0';
871 END IF;
872 -- Terminate a Read depend on CAS Latency
873 IF CAS_latency_3 = '1' THEN
874 Command(2) := BST;
875 ELSIF CAS_latency_2 = '1' THEN
876 Command(1) := BST;
877 END IF;
878 END IF;
879
880 -- Read, Write, Column Latch
881 IF Read_enable = '1' OR Write_enable = '1' THEN
882 -- Check to see if bank is open (ACT) for Read or Write
883 IF ((Ba="00" AND Pc_b0='1') OR (Ba="01" AND Pc_b1='1') OR (Ba="10" AND Pc_b2='1') OR (Ba="11" AND Pc_b3='1')) THEN
884 ASSERT (FALSE)
885 REPORT "Cannot Read or Write - Bank is not Activated"
886 SEVERITY WARNING;
887 END IF;
888 -- Activate to Read or Write
889 IF Ba = "00" THEN
890 ASSERT (NOW - RCD_chk0 >= tRCD)
891 REPORT "tRCD violation during Read or Write to Bank 0"
892 SEVERITY WARNING;
893 ELSIF Ba = "01" THEN
894 ASSERT (NOW - RCD_chk1 >= tRCD)
895 REPORT "tRCD violation during Read or Write to Bank 1"
896 SEVERITY WARNING;
897 ELSIF Ba = "10" THEN
898 ASSERT (NOW - RCD_chk2 >= tRCD)
899 REPORT "tRCD violation during Read or Write to Bank 2"
900 SEVERITY WARNING;
901 ELSIF Ba = "11" THEN
902 ASSERT (NOW - RCD_chk3 >= tRCD)
903 REPORT "tRCD violation during Read or Write to Bank 3"
904 SEVERITY WARNING;
905 END IF;
906
907 -- Read Command
908 IF Read_enable = '1' THEN
909 -- CAS Latency Pipeline
910 IF Cas_latency_3 = '1' THEN
911 IF Addr(10) = '1' THEN
912 Command(2) := READ_A;
913 ELSE
914 Command(2) := READ;
915 END IF;
916 Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
917 Bank_addr (2) := TO_BITVECTOR (Ba);
918 ELSIF Cas_latency_2 = '1' THEN
919 IF Addr(10) = '1' THEN
920 Command(1) := READ_A;
921 ELSE
922 Command(1) := READ;
923 END IF;
924 Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
925 Bank_addr (1) := TO_BITVECTOR (Ba);
926 END IF;
927
928 -- Read intterupt a Write (terminate Write immediately)
929 IF Data_in_enable = '1' THEN
930 Data_in_enable := '0';
931 END IF;
932
933 -- Write Command
934 ELSIF Write_enable = '1' THEN
935 IF Addr(10) = '1' THEN
936 Command(0) := WRITE_A;
937 ELSE
938 Command(0) := WRITE;
939 END IF;
940 Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
941 Bank_addr (0) := TO_BITVECTOR (Ba);
942
943 -- Write intterupt a Write (terminate Write immediately)
944 IF Data_in_enable = '1' THEN
945 Data_in_enable := '0';
946 END IF;
947
948 -- Write interrupt a Read (terminate Read immediately)
949 IF Data_out_enable = '1' THEN
950 Data_out_enable := '0';
951 END IF;
952 END IF;
953
954 -- Interrupt a Write with Auto Precharge
955 IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Write_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN
956 RW_interrupt_write(TO_INTEGER(RW_Interrupt_Bank)) := '1';
957 END IF;
958
959 -- Interrupt a Read with Auto Precharge
960 IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Read_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN
961 RW_interrupt_read(TO_INTEGER(RW_Interrupt_Bank)) := '1';
962 END IF;
963
964 -- Read or Write with Auto Precharge
965 IF Addr(10) = '1' THEN
966 Auto_precharge (TO_INTEGER(Ba)) := '1';
967 Count_precharge (TO_INTEGER(Ba)) := 0;
968 RW_Interrupt_Bank := TO_BitVector(Ba);
969 IF Read_enable = '1' THEN
970 Read_precharge (TO_INTEGER(Ba)) := '1';
971 ELSIF Write_enable = '1' THEN
972 Write_precharge (TO_INTEGER(Ba)) := '1';
973 END IF;
974 END IF;
975 END IF;
976
977 -- Read with AutoPrecharge Calculation
978 -- The device start internal precharge when:
979 -- 1. BL/2 cycles after command
980 -- and 2. Meet tRAS requirement
981 -- or 3. Interrupt by a Read or Write (with or without Auto Precharge)
982 IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN
983 IF (((NOW - RAS_chk0 >= tRAS) AND
984 ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR
985 (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR
986 (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR
987 (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR
988 (RW_interrupt_read(0) = '1')) THEN
989 Pc_b0 := '1';
990 Act_b0 := '0';
991 RP_chk0 := NOW;
992 Auto_precharge(0) := '0';
993 Read_precharge(0) := '0';
994 RW_interrupt_read(0) := '0';
995 END IF;
996 END IF;
997 IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN
998 IF (((NOW - RAS_chk1 >= tRAS) AND
999 ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR
1000 (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR
1001 (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR
1002 (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR
1003 (RW_interrupt_read(1) = '1')) THEN
1004 Pc_b1 := '1';
1005 Act_b1 := '0';
1006 RP_chk1 := NOW;
1007 Auto_precharge(1) := '0';
1008 Read_precharge(1) := '0';
1009 RW_interrupt_read(1) := '0';
1010 END IF;
1011 END IF;
1012 IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN
1013 IF (((NOW - RAS_chk2 >= tRAS) AND
1014 ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR
1015 (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR
1016 (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR
1017 (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR
1018 (RW_interrupt_read(2) = '1')) THEN
1019 Pc_b2 := '1';
1020 Act_b2 := '0';
1021 RP_chk2 := NOW;
1022 Auto_precharge(2) := '0';
1023 Read_precharge(2) := '0';
1024 RW_interrupt_read(2) := '0';
1025 END IF;
1026 END IF;
1027 IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN
1028 IF (((NOW - RAS_chk3 >= tRAS) AND
1029 ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR
1030 (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR
1031 (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR
1032 (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR
1033 (RW_interrupt_read(3) = '1')) THEN
1034 Pc_b3 := '1';
1035 Act_b3 := '0';
1036 RP_chk3 := NOW;
1037 Auto_precharge(3) := '0';
1038 Read_precharge(3) := '0';
1039 RW_interrupt_read(3) := '0';
1040 END IF;
1041 END IF;
1042
1043 -- Internal Precharge or Bst
1044 IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks
1045 IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN
1046 IF Data_out_enable = '1' THEN
1047 Data_out_enable := '0';
1048 END IF;
1049 END IF;
1050 ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank
1051 IF Data_out_enable = '1' THEN
1052 Data_out_enable := '0';
1053 END IF;
1054 END IF;
1055
1056 IF Data_out_enable = '0' THEN
1057 Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH;
1058 END IF;
1059
1060 -- Detect Read or Write Command
1061 IF Command(0) = READ OR Command(0) = READ_A THEN
1062 Bank := Bank_addr (0);
1063 Col := Col_addr (0);
1064 Col_brst := Col_addr (0);
1065 IF Bank_addr (0) = "00" THEN
1066 Row := B0_row_addr;
1067 ELSIF Bank_addr (0) = "01" THEN
1068 Row := B1_row_addr;
1069 ELSIF Bank_addr (0) = "10" THEN
1070 Row := B2_row_addr;
1071 ELSE
1072 Row := B3_row_addr;
1073 END IF;
1074 Burst_counter := 0;
1075 Data_in_enable := '0';
1076 Data_out_enable := '1';
1077 ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN
1078 Bank := Bank_addr(0);
1079 Col := Col_addr(0);
1080 Col_brst := Col_addr(0);
1081 IF Bank_addr (0) = "00" THEN
1082 Row := B0_row_addr;
1083 ELSIF Bank_addr (0) = "01" THEN
1084 Row := B1_row_addr;
1085 ELSIF Bank_addr (0) = "10" THEN
1086 Row := B2_row_addr;
1087 ELSE
1088 Row := B3_row_addr;
1089 END IF;
1090 Burst_counter := 0;
1091 Data_in_enable := '1';
1092 Data_out_enable := '0';
1093 END IF;
1094
1095 -- DQ (Driver / Receiver)
1096 Row_index := TO_INTEGER (Row);
1097 Col_index := TO_INTEGER (Col);
1098 IF Data_in_enable = '1' THEN
1099 IF Dqm /= "11" THEN
1100 Init_mem (Bank, Row_index);
1101 IF Bank = "00" THEN
1102 Dq_temp := Bank0 (Row_index) (Col_index);
1103 IF Dqm = "01" THEN
1104 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1105 ELSIF Dqm = "10" THEN
1106 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1107 ELSE
1108 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1109 END IF;
1110 Bank0 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1111 ELSIF Bank = "01" THEN
1112 Dq_temp := Bank1 (Row_index) (Col_index);
1113 IF Dqm = "01" THEN
1114 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1115 ELSIF Dqm = "10" THEN
1116 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1117 ELSE
1118 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1119 END IF;
1120 Bank1 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1121 ELSIF Bank = "10" THEN
1122 Dq_temp := Bank2 (Row_index) (Col_index);
1123 IF Dqm = "01" THEN
1124 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1125 ELSIF Dqm = "10" THEN
1126 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1127 ELSE
1128 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1129 END IF;
1130 Bank2 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1131 ELSIF Bank = "11" THEN
1132 Dq_temp := Bank3 (Row_index) (Col_index);
1133 IF Dqm = "01" THEN
1134 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1135 ELSIF Dqm = "10" THEN
1136 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1137 ELSE
1138 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1139 END IF;
1140 Bank3 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1141 END IF;
1142 WR_chkp(TO_INTEGER(Bank)) := NOW;
1143 WR_counter(TO_INTEGER(Bank)) := 0;
1144 END IF;
1145 Burst_decode;
1146 ELSIF Data_out_enable = '1' THEN
1147 IF Dqm_reg0 /= "11" THEN
1148 Init_mem (Bank, Row_index);
1149 IF Bank = "00" THEN
1150 Dq_temp := Bank0 (Row_index) (Col_index);
1151 IF Dqm_reg0 = "00" THEN
1152 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1153 ELSIF Dqm_reg0 = "01" THEN
1154 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1155 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1156 ELSIF Dqm_reg0 = "10" THEN
1157 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1158 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1159 END IF;
1160 ELSIF Bank = "01" THEN
1161 Dq_temp := Bank1 (Row_index) (Col_index);
1162 IF Dqm_reg0 = "00" THEN
1163 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1164 ELSIF Dqm_reg0 = "01" THEN
1165 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1166 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1167 ELSIF Dqm_reg0 = "10" THEN
1168 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1169 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1170 END IF;
1171 ELSIF Bank = "10" THEN
1172 Dq_temp := Bank2 (Row_index) (Col_index);
1173 IF Dqm_reg0 = "00" THEN
1174 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1175 ELSIF Dqm_reg0 = "01" THEN
1176 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1177 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1178 ELSIF Dqm_reg0 = "10" THEN
1179 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1180 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1181 END IF;
1182 ELSIF Bank = "11" THEN
1183 Dq_temp := Bank3 (Row_index) (Col_index);
1184 IF Dqm_reg0 = "00" THEN
1185 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1186 ELSIF Dqm_reg0 = "01" THEN
1187 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1188 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1189 ELSIF Dqm_reg0 = "10" THEN
1190 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1191 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1192 END IF;
1193 END IF;
1194 ELSE
1195 Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ;
1196 END IF;
1197 Burst_decode;
1198 END IF;
1199 ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '1' AND Dump = '0' THEN --'
1200 Operation <= LOAD_FILE;
1201 load := '0';
1202 -- ASSERT (FALSE) REPORT "Reading memory array from file. This operation may take several minutes. Please wait..."
1203 -- SEVERITY NOTE;
1204 WHILE NOT endfile(file_load) LOOP
1205 readline(file_load, l);
1206 read(l, ch);
1207 if (ch /= 'S') or (ch /= 's') then
1208 hread(l, rectype);
1209 hread(l, reclen);
1210 recaddr := (others => '0');
1211 case rectype is
1212 when "0001" =>
1213 hread(l, recaddr(15 downto 0));
1214 when "0010" =>
1215 hread(l, recaddr(23 downto 0));
1216 when "0011" =>
1217 hread(l, recaddr);
1218 recaddr(31 downto 24) := (others => '0');
1219 when others => next;
1220 end case;
1221 hread(l, recdata);
1222
1223 if index < 32 then
1224 Bank_Load := recaddr(25 downto 24);
1225 Rows_Load := recaddr(23 downto 11);
1226 Cols_Load := recaddr(10 downto 2);
1227 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1228 IF Bank_Load = "00" THEN
1229 for i in 0 to 3 loop
1230 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1231 end loop;
1232 ELSIF Bank_Load = "01" THEN
1233 for i in 0 to 3 loop
1234 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1235 end loop;
1236 ELSIF Bank_Load = "10" THEN
1237 for i in 0 to 3 loop
1238 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1239 end loop;
1240 ELSIF Bank_Load = "11" THEN
1241 for i in 0 to 3 loop
1242 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1243 end loop;
1244 END IF;
1245 elsif(index < 1024) then
1246 Bank_Load := recaddr(26 downto 25);
1247 Rows_Load := recaddr(24 downto 12);
1248 Cols_Load := recaddr(11 downto 3);
1249 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1250 IF Bank_Load = "00" THEN
1251 for i in 0 to 1 loop
1252 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1253 end loop;
1254 ELSIF Bank_Load = "01" THEN
1255 for i in 0 to 1 loop
1256 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1257 end loop;
1258 ELSIF Bank_Load = "10" THEN
1259 for i in 0 to 1 loop
1260 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1261 end loop;
1262 ELSIF Bank_Load = "11" THEN
1263 for i in 0 to 1 loop
1264 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1265 end loop;
1266 END IF;
1267 else
1268 Bank_Load := recaddr(22 downto 21);
1269 Rows_Load := '0' & recaddr(20 downto 9);
1270 Cols_Load := '0' & recaddr(8 downto 1);
1271 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1272 IF Bank_Load = "00" THEN
1273 for i in 0 to 7 loop
1274 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1275 end loop;
1276 ELSIF Bank_Load = "01" THEN
1277 for i in 0 to 7 loop
1278 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1279 end loop;
1280 ELSIF Bank_Load = "10" THEN
1281 for i in 0 to 7 loop
1282 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1283 end loop;
1284 ELSIF Bank_Load = "11" THEN
1285 for i in 0 to 7 loop
1286 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1287 end loop;
1288 END IF;
1289 END IF;
1290 END IF;
1291 END LOOP;
1292 ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '1' THEN --'
1293 Operation <= DUMP_FILE;
1294 ASSERT (FALSE) REPORT "Writing memory array to file. This operation may take several minutes. Please wait..."
1295 SEVERITY NOTE;
1296 WRITE (l, string'("# Micron Technology, Inc. (FILE DUMP / MEMORY DUMP)")); --'
1297 WRITELINE (file_dump, l);
1298 WRITE (l, string'("# BA ROWS COLS DQ")); --'
1299 WRITELINE (file_dump, l);
1300 WRITE (l, string'("# -- ------------- --------- ----------------")); --'
1301 WRITELINE (file_dump, l);
1302 -- Dumping Bank 0
1303 FOR i IN 0 TO 2**addr_bits -1 LOOP
1304 -- Check if ROW is NULL
1305 IF Bank0 (i) /= NULL THEN
1306 For j IN 0 TO 2**col_bits - 1 LOOP
1307 -- Check if COL is NULL
1308 NEXT WHEN Bank0 (i) (j) (data_bits) = '0';
1309 WRITE (l, string'("00"), right, 4); --'
1310 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1311 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1312 WRITE (l, Bank0 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1313 WRITELINE (file_dump, l);
1314 END LOOP;
1315 END IF;
1316 END LOOP;
1317 -- Dumping Bank 1
1318 FOR i IN 0 TO 2**addr_bits -1 LOOP
1319 -- Check if ROW is NULL
1320 IF Bank1 (i) /= NULL THEN
1321 For j IN 0 TO 2**col_bits - 1 LOOP
1322 -- Check if COL is NULL
1323 NEXT WHEN Bank1 (i) (j) (data_bits) = '0';
1324 WRITE (l, string'("01"), right, 4); --'
1325 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1326 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1327 WRITE (l, Bank1 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1328 WRITELINE (file_dump, l);
1329 END LOOP;
1330 END IF;
1331 END LOOP;
1332 -- Dumping Bank 2
1333 FOR i IN 0 TO 2**addr_bits -1 LOOP
1334 -- Check if ROW is NULL
1335 IF Bank2 (i) /= NULL THEN
1336 For j IN 0 TO 2**col_bits - 1 LOOP
1337 -- Check if COL is NULL
1338 NEXT WHEN Bank2 (i) (j) (data_bits) = '0';
1339 WRITE (l, string'("10"), right, 4); --'
1340 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1341 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1342 WRITE (l, Bank2 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1343 WRITELINE (file_dump, l);
1344 END LOOP;
1345 END IF;
1346 END LOOP;
1347 -- Dumping Bank 3
1348 FOR i IN 0 TO 2**addr_bits -1 LOOP
1349 -- Check if ROW is NULL
1350 IF Bank3 (i) /= NULL THEN
1351 For j IN 0 TO 2**col_bits - 1 LOOP
1352 -- Check if COL is NULL
1353 NEXT WHEN Bank3 (i) (j) (data_bits) = '0';
1354 WRITE (l, string'("11"), right, 4); --'
1355 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1356 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1357 WRITE (l, Bank3 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1358 WRITELINE (file_dump, l);
1359 END LOOP;
1360 END IF;
1361 END LOOP;
1362 END IF;
1363
1364 -- Write with AutoPrecharge Calculation
1365 -- The device start internal precharge when:
1366 -- 1. tWR cycles after command
1367 -- and 2. Meet tRAS requirement
1368 -- or 3. Interrupt by a Read or Write (with or without Auto Precharge)
1369 IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN
1370 IF (((NOW - RAS_chk0 >= tRAS) AND
1371 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR
1372 (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR
1373 (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR
1374 (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR
1375 (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN
1376 Auto_precharge(0) := '0';
1377 Write_precharge(0) := '0';
1378 RW_interrupt_write(0) := '0';
1379 Pc_b0 := '1';
1380 Act_b0 := '0';
1381 RP_chk0 := NOW;
1382 ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE;
1383 END IF;
1384 END IF;
1385 IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN
1386 IF (((NOW - RAS_chk1 >= tRAS) AND
1387 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR
1388 (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR
1389 (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR
1390 (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR
1391 (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN
1392 Auto_precharge(1) := '0';
1393 Write_precharge(1) := '0';
1394 RW_interrupt_write(1) := '0';
1395 Pc_b1 := '1';
1396 Act_b1 := '0';
1397 RP_chk1 := NOW;
1398 END IF;
1399 END IF;
1400 IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN
1401 IF (((NOW - RAS_chk2 >= tRAS) AND
1402 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR
1403 (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR
1404 (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR
1405 (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR
1406 (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN
1407 Auto_precharge(2) := '0';
1408 Write_precharge(2) := '0';
1409 RW_interrupt_write(2) := '0';
1410 Pc_b2 := '1';
1411 Act_b2 := '0';
1412 RP_chk2 := NOW;
1413 END IF;
1414 END IF;
1415 IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN
1416 IF (((NOW - RAS_chk3 >= tRAS) AND
1417 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR
1418 (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR
1419 (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR
1420 (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR
1421 (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN
1422 Auto_precharge(3) := '0';
1423 Write_precharge(3) := '0';
1424 RW_interrupt_write(3) := '0';
1425 Pc_b3 := '1';
1426 Act_b3 := '0';
1427 RP_chk3 := NOW;
1428 END IF;
1429 END IF;
1430
1431 -- Checking internal wires (Optional for debug purpose)
1432 Pre_chk (0) <= Pc_b0;
1433 Pre_chk (1) <= Pc_b1;
1434 Pre_chk (2) <= Pc_b2;
1435 Pre_chk (3) <= Pc_b3;
1436 Act_chk (0) <= Act_b0;
1437 Act_chk (1) <= Act_b1;
1438 Act_chk (2) <= Act_b2;
1439 Act_chk (3) <= Act_b3;
1440 Dq_in_chk <= Data_in_enable;
1441 Dq_out_chk <= Data_out_enable;
1442 Bank_chk <= Bank;
1443 Row_chk <= Row;
1444 Col_chk <= Col;
1445 END PROCESS;
1446
1447
1448 -- Clock timing checks
1449 -- Clock_check : PROCESS
1450 -- VARIABLE Clk_low, Clk_high : TIME := 0 ns;
1451 -- BEGIN
1452 -- WAIT ON Clk;
1453 -- IF (Clk = '1' AND NOW >= 10 ns) THEN
1454 -- ASSERT (NOW - Clk_low >= tCL)
1455 -- REPORT "tCL violation"
1456 -- SEVERITY WARNING;
1457 -- ASSERT (NOW - Clk_high >= tCK)
1458 -- REPORT "tCK violation"
1459 -- SEVERITY WARNING;
1460 -- Clk_high := NOW;
1461 -- ELSIF (Clk = '0' AND NOW /= 0 ns) THEN
1462 -- ASSERT (NOW - Clk_high >= tCH)
1463 -- REPORT "tCH violation"
1464 -- SEVERITY WARNING;
1465 -- Clk_low := NOW;
1466 -- END IF;
1467 -- END PROCESS;
1468
1469 -- Setup timing checks
1470 Setup_check : PROCESS
1471 BEGIN
1472 wait;
1473 WAIT ON Clk;
1474 IF Clk = '1' THEN
1475 ASSERT(Cke'LAST_EVENT >= tCKS) --'
1476 REPORT "CKE Setup time violation -- tCKS"
1477 SEVERITY WARNING;
1478 ASSERT(Cs_n'LAST_EVENT >= tCMS) --'
1479 REPORT "CS# Setup time violation -- tCMS"
1480 SEVERITY WARNING;
1481 ASSERT(Cas_n'LAST_EVENT >= tCMS) --'
1482 REPORT "CAS# Setup time violation -- tCMS"
1483 SEVERITY WARNING;
1484 ASSERT(Ras_n'LAST_EVENT >= tCMS) --'
1485 REPORT "RAS# Setup time violation -- tCMS"
1486 SEVERITY WARNING;
1487 ASSERT(We_n'LAST_EVENT >= tCMS) --'
1488 REPORT "WE# Setup time violation -- tCMS"
1489 SEVERITY WARNING;
1490 ASSERT(Dqm'LAST_EVENT >= tCMS) --'
1491 REPORT "Dqm Setup time violation -- tCMS"
1492 SEVERITY WARNING;
1493 ASSERT(Addr'LAST_EVENT >= tAS) --'
1494 REPORT "ADDR Setup time violation -- tAS"
1495 SEVERITY WARNING;
1496 ASSERT(Ba'LAST_EVENT >= tAS) --'
1497 REPORT "BA Setup time violation -- tAS"
1498 SEVERITY WARNING;
1499 ASSERT(Dq'LAST_EVENT >= tDS) --'
1500 REPORT "Dq Setup time violation -- tDS"
1501 SEVERITY WARNING;
1502 END IF;
1503 END PROCESS;
1504
1505 -- Hold timing checks
1506 Hold_check : PROCESS
1507 BEGIN
1508 wait;
1509 WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH);
1510 IF Clk'DELAYED (tCKH) = '1' THEN --'
1511 ASSERT(Cke'LAST_EVENT > tCKH) --'
1512 REPORT "CKE Hold time violation -- tCKH"
1513 SEVERITY WARNING;
1514 END IF;
1515 IF Clk'DELAYED (tCMH) = '1' THEN --'
1516 ASSERT(Cs_n'LAST_EVENT > tCMH) --'
1517 REPORT "CS# Hold time violation -- tCMH"
1518 SEVERITY WARNING;
1519 ASSERT(Cas_n'LAST_EVENT > tCMH) --'
1520 REPORT "CAS# Hold time violation -- tCMH"
1521 SEVERITY WARNING;
1522 ASSERT(Ras_n'LAST_EVENT > tCMH) --'
1523 REPORT "RAS# Hold time violation -- tCMH"
1524 SEVERITY WARNING;
1525 ASSERT(We_n'LAST_EVENT > tCMH) --'
1526 REPORT "WE# Hold time violation -- tCMH"
1527 SEVERITY WARNING;
1528 ASSERT(Dqm'LAST_EVENT > tCMH) --'
1529 REPORT "Dqm Hold time violation -- tCMH"
1530 SEVERITY WARNING;
1531 END IF;
1532 IF Clk'DELAYED (tAH) = '1' THEN --'
1533 ASSERT(Addr'LAST_EVENT > tAH) --'
1534 REPORT "ADDR Hold time violation -- tAH"
1535 SEVERITY WARNING;
1536 ASSERT(Ba'LAST_EVENT > tAH) --'
1537 REPORT "BA Hold time violation -- tAH"
1538 SEVERITY WARNING;
1539 END IF;
1540 IF Clk'DELAYED (tDH) = '1' THEN --'
1541 ASSERT(Dq'LAST_EVENT > tDH) --'
1542 REPORT "Dq Hold time violation -- tDH"
1543 SEVERITY WARNING;
1544 END IF;
1545 END PROCESS;
1546
1547 END behave;
1548
1549 -- pragma translate_on
1550
@@ -0,0 +1,69
1 <?xml version='1.0' encoding='utf-8'?>
2 <soc name="Leon">
3 <peripheral vid="8" name="SpaceWire Light" pid="305">
4 <register name="Control register" addOffset="0">
5 <bitField size="1" offset="0" name="Reset" mode="3" desc="Write '1' to reset SPWAMBA core (auto-clear)."/>
6 <bitField size="1" offset="1" name="Reset DMA" mode="3" desc="Write '1' to reset DMA engines (auto-clear)."/>
7 <bitField name="Link Start" offset="2" size="1" mode="3" desc="Link start signal. '1' = actively try to start a SpaceWire link."/>
8 <bitField name="Link Auto Start" offset="3" size="1" mode="3" desc="Link autostart signal. '1' = start link after receiving NULL from other side."/>
9 <bitField name="Link Disable" offset="4" size="1" mode="3" desc="Link disable signal. '1' = shut down current link and do not establish new link."/>
10 <bitField name="Time Code EN" offset="5" size="1" mode="3" desc="Allow time-code transmission through tick_in signal."/>
11 <bitField name="Restart RX DMA" offset="6" size="1" mode="3" desc="Write '1' to (re-)start RX DMA (auto-clear)."/>
12 <bitField name="Restart TX DMA" offset="7" size="1" mode="3" desc="Write '1' to (re-)start TX DMA (auto-clear)."/>
13 <bitField name="Cancel TX DMA" offset="8" size="1" mode="3" desc="Write '1' to cancel running TX DMA and discard data from TX FIFO (auto-clear)."/>
14 <bitField name="Link Up/Down IE" offset="9" size="1" mode="3" desc="Enable interrupt on link up/down."/>
15 <bitField name="Time Code IE" offset="10" size="1" mode="3" desc="Enable interrupt on time code received."/>
16 <bitField name="RXDESCIE" offset="11" size="1" mode="3" desc="Enable interrupt on completed RX descriptor with IE='1'."/>
17 <bitField name="TXDESCIE" offset="12" size="1" mode="3" desc="Enable interrupt on completed TX descriptor with IE='1'."/>
18 <bitField name="RXIE" offset="13" size="1" mode="3" desc="Enable interrupt on RX packet received."/>
19 <bitField name="DescSz" offset="24" size="4" mode="1" desc="Value of desctablesize generic (read-only)."/>
20 </register>
21 <register name="Status register" addOffset="4">
22 <bitField size="2" offset="0" name="LSTAT" mode="1" desc="Link status: 0=off, 1=started, 2=connecting, 3=run (read-only)."/>
23 <bitField size="1" offset="2" name="DISCERR" mode="3" desc="Got disconnect error (sticky, write '1' to clear)."/>
24 <bitField size="1" offset="3" name="PARERR" mode="3" desc="Got parity error (sticky, write '1' to clear)."/>
25 <bitField size="1" offset="4" name="ESCERR" mode="3" desc="Got escape error (sticky, write '1' to clear)."/>
26 <bitField size="1" offset="5" name="CREDERR" mode="3" desc="Got credit error (sticky, write '1' to clear)."/>
27 <bitField size="1" offset="6" name="RXDMA" mode="1" desc="RX DMA running (read-only)."/>
28 <bitField size="1" offset="7" name="RXDMA" mode="1" desc="TX DMA running (read-only)."/>
29 <bitField size="1" offset="8" name="AHBERR" mode="1" desc="AHB error occurred (sticky, reset DMA engine to clear)."/>
30 <bitField size="1" offset="9" name="UNUSED" mode="3" desc="unused"/>
31 <bitField size="1" offset="10" name="TIMECODE" mode="3" desc="Received time-code (sticky, write '1' to clear)."/>
32 <bitField size="1" offset="11" name="RXDESCCOMP" mode="3" desc="Completed RX descriptor with IE='1' (sticky, write '1' to clear)."/>
33 <bitField size="1" offset="12" name="TXDESCCOMP" mode="3" desc="Completed TX descriptor with IE='1' (sticky, write '1' to clear)."/>
34 <bitField size="1" offset="13" name="RECPACKT" mode="3" desc="Received packet (sticky, write '1' to clear)."/>
35 <bitField size="1" offset="14" name="RXE" mode="1" desc="RX buffer is empty and last packet has been completely transfered to RX DMA (read-only)."/>
36 </register>
37 <register name="Transmission clock scaler" addOffset="8">
38 <bitField size="8" offset="0" name="N" mode="3" desc="Clock division factor minus 1. The actual TX bit rate is determined by (txclk frequency) / (scaler + 1).
39 During the handshake phase, this register is ignored and the TX bit rate is forced to 10 Mbit. After reset, this
40 register defaults to the scaler value needed for 10 Mbit."/>
41 </register>
42 <register name="Time-code register" addOffset="12">
43 <bitField size="6" offset="0" name="Address" mode="1" desc="Last received time-code value (read-only)."/>
44 <bitField size="2" offset="6" name="Address" mode="1" desc="Control bits received with last time-code (read-only)."/>
45 <bitField size="6" offset="12" name="Address" mode="3" desc="Time-code value to send on next tick_in (auto-increment)."/>
46 <bitField size="2" offset="14" name="Address" mode="3" desc="Reserved, write as zero."/>
47 <bitField size="1" offset="15" name="Address" mode="3" desc="Write '1' to send a time-code immediately (auto-clear)."/>
48 </register>
49 <register name="Descriptor pointer for RX DMA" addOffset="16">
50 <bitField size="3" offset="0" name="DATA" mode="3" desc="Reserved, write as zero."/>
51 <bitField size="10" offset="3" name="DATA" mode="3" desc="Descriptor index (auto-increment)."/>
52 <bitField size="19" offset="13" name="DATA" mode="3" desc="Fixed address bits of descriptor table."/>
53 </register>
54 <register name="Descriptor pointer for TX DMA" addOffset="20">
55 <bitField size="3" offset="0" name="DATA" mode="3" desc="Reserved, write as zero."/>
56 <bitField size="10" offset="3" name="DATA" mode="3" desc="Descriptor index (auto-increment)."/>
57 <bitField size="19" offset="13" name="DATA" mode="3" desc="Fixed address bits of descriptor table."/>
58 </register>
59 </peripheral>
60 </soc>
61
62
63
64
65
66
67
68
69
This diff has been collapsed as it changes many lines, (1053 lines changed) Show them Hide them
@@ -0,0 +1,1053
1 ------------------------------------------------------------------------------
2 -- This file is a part of the GRLIB VHDL IP LIBRARY
3 -- Copyright (C) 2003 - 2008, Gaisler Research
4 -- Copyright (C) 2008 - 2014, Aeroflex Gaisler
5 -- Copyright (C) 2015 - 2016, Cobham Gaisler
6 --
7 -- This program is free software; you can redistribute it and/or modify
8 -- it under the terms of the GNU General Public License as published by
9 -- the Free Software Foundation; either version 2 of the License, or
10 -- (at your option) any later version.
11 --
12 -- This program is distributed in the hope that it will be useful,
13 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 -- GNU General Public License for more details.
16 --
17 -- You should have received a copy of the GNU General Public License
18 -- along with this program; if not, write to the Free Software
19 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 -----------------------------------------------------------------------------
21 -- Entity: sdctrl16
22 -- File: sdctrl16.vhd
23 -- Author: Jiri Gaisler - Gaisler Research
24 -- Modified by: Daniel Bengtsson & Richard Fång
25 -- Description: 16- and 32-bit SDRAM memory controller.
26 ------------------------------------------------------------------------------
27
28 library ieee;
29 use ieee.std_logic_1164.all;
30 library grlib;
31 use grlib.amba.all;
32 use grlib.stdlib.all;
33 library gaisler;
34 use grlib.devices.all;
35 use gaisler.memctrl.all;
36
37 entity sdctrl16 is
38 generic (
39 hindex : integer := 0;
40 haddr : integer := 0;
41 hmask : integer := 16#f00#;
42 ioaddr : integer := 16#000#;
43 iomask : integer := 16#fff#;
44 wprot : integer := 0;
45 invclk : integer := 0;
46 fast : integer := 0;
47 pwron : integer := 0;
48 sdbits : integer := 16;
49 oepol : integer := 0;
50 pageburst : integer := 0;
51 mobile : integer := 0
52 );
53 port (
54 rst : in std_ulogic;
55 clk : in std_ulogic;
56 ahbsi : in ahb_slv_in_type;
57 ahbso : out ahb_slv_out_type;
58 sdi : in sdctrl_in_type;
59 sdo : out sdctrl_out_type
60 );
61 end;
62
63 architecture rtl of sdctrl16 is
64
65 constant WPROTEN : boolean := wprot = 1;
66 constant SDINVCLK : boolean := invclk = 1;
67 constant BUS16 : boolean := (sdbits = 16);
68 constant BUS32 : boolean := (sdbits = 32);
69 constant BUS64 : boolean := (sdbits = 64);
70
71 constant REVISION : integer := 1;
72
73 constant PM_PD : std_logic_vector(2 downto 0) := "001";
74 constant PM_SR : std_logic_vector(2 downto 0) := "010";
75 constant PM_DPD : std_logic_vector(2 downto 0) := "101";
76
77 constant std_rammask: Std_Logic_Vector(31 downto 20) :=
78 Conv_Std_Logic_Vector(hmask, 12);
79
80 constant hconfig : ahb_config_type := (
81 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_SDCTRL, 0, REVISION, 0),
82 4 => ahb_membar(haddr, '1', '1', hmask),
83 5 => ahb_iobar(ioaddr, iomask),
84 others => zero32);
85
86 type mcycletype is (midle, active, leadout);
87 type sdcycletype is (act1, act2, act3, act3_16, rd1, rd2, rd3, rd4, rd4_16, rd5, rd6, rd7, rd8,
88 wr1, wr1_16, wr2, wr3, wr4, wr5, sidle,
89 sref, pd, dpd);
90 type icycletype is (iidle, pre, ref, lmode, emode, finish);
91
92 -- sdram configuration register
93
94 type sdram_cfg_type is record
95 command : std_logic_vector(2 downto 0);
96 csize : std_logic_vector(1 downto 0);
97 bsize : std_logic_vector(2 downto 0);
98 casdel : std_ulogic; -- CAS to data delay: 2/3 clock cycles
99 trfc : std_logic_vector(2 downto 0);
100 trp : std_ulogic; -- precharge to activate: 2/3 clock cycles
101 refresh : std_logic_vector(14 downto 0);
102 renable : std_ulogic;
103 pageburst : std_ulogic;
104 mobileen : std_logic_vector(1 downto 0); -- Mobile SD support, Mobile SD enabled
105 ds : std_logic_vector(3 downto 0); -- ds(1:0) (ds(3:2) used to detect update)
106 tcsr : std_logic_vector(3 downto 0); -- tcrs(1:0) (tcrs(3:2) used to detect update)
107 pasr : std_logic_vector(5 downto 0); -- pasr(2:0) (pasr(5:3) used to detect update)
108 pmode : std_logic_vector(2 downto 0); -- Power-Saving mode
109 txsr : std_logic_vector(3 downto 0); -- Exit Self Refresh timing
110 cke : std_ulogic; -- Clock enable
111 end record;
112
113 -- local registers
114
115 type reg_type is record
116 hready : std_ulogic;
117 hsel : std_ulogic;
118 bdrive : std_ulogic;
119 nbdrive : std_ulogic;
120 burst : std_ulogic;
121 wprothit : std_ulogic;
122 hio : std_ulogic;
123 startsd : std_ulogic;
124 lhw : std_ulogic; --Lower halfword
125
126 mstate : mcycletype;
127 sdstate : sdcycletype;
128 cmstate : mcycletype;
129 istate : icycletype;
130 icnt : std_logic_vector(2 downto 0);
131
132 haddr : std_logic_vector(31 downto 0);
133 hrdata : std_logic_vector((sdbits-1)+((16/sdbits)*16) downto 0);
134 hwdata : std_logic_vector(31 downto 0);
135 hwrite : std_ulogic;
136 htrans : std_logic_vector(1 downto 0);
137 hresp : std_logic_vector(1 downto 0);
138 size : std_logic_vector(1 downto 0);
139
140 cfg : sdram_cfg_type;
141 trfc : std_logic_vector(3 downto 0);
142 refresh : std_logic_vector(14 downto 0);
143 sdcsn : std_logic_vector(1 downto 0);
144 sdwen : std_ulogic;
145 rasn : std_ulogic;
146 casn : std_ulogic;
147 dqm : std_logic_vector(7 downto 0);
148 address : std_logic_vector(16 downto 2); -- memory address
149 bsel : std_ulogic;
150
151 idlecnt : std_logic_vector(3 downto 0); -- Counter, 16 idle clock sycles before entering Power-Saving mode
152 sref_tmpcom : std_logic_vector(2 downto 0); -- Save SD command when exit sref
153 end record;
154
155 signal r, ri : reg_type;
156 signal rbdrive, ribdrive : std_logic_vector(31 downto 0);
157 attribute syn_preserve : boolean;
158 attribute syn_preserve of rbdrive : signal is true;
159
160 begin
161
162 ctrl : process(rst, ahbsi, r, sdi, rbdrive)
163 variable v : reg_type; -- local variables for registers
164 variable startsd : std_ulogic;
165 variable dataout : std_logic_vector(31 downto 0); -- data from memory
166 variable regsd : std_logic_vector(31 downto 0); -- data from registers
167 variable dqm : std_logic_vector(7 downto 0);
168 variable raddr : std_logic_vector(12 downto 0);
169 variable adec : std_ulogic;
170 variable rams : std_logic_vector(1 downto 0);
171 variable ba : std_logic_vector(1 downto 0);
172 variable haddr : std_logic_vector(31 downto 0);
173 variable dout : std_logic_vector(31 downto 0);
174 variable hsize : std_logic_vector(1 downto 0);
175 variable hwrite : std_ulogic;
176 variable htrans : std_logic_vector(1 downto 0);
177 variable hready : std_ulogic;
178 variable vbdrive : std_logic_vector(31 downto 0);
179 variable bdrive : std_ulogic;
180 variable lline : std_logic_vector(2 downto 0);
181 variable lineburst : boolean;
182 variable haddr_tmp : std_logic_vector(31 downto 0);
183 variable arefresh : std_logic;
184 variable hwdata : std_logic_vector(31 downto 0);
185
186 begin
187
188 -- Variable default settings to avoid latches
189
190 v := r; startsd := '0'; v.hresp := HRESP_OKAY; vbdrive := rbdrive; arefresh := '0';
191 if BUS16 then
192 if (r.lhw = '1') then --muxes read data to correct part of the register.
193 v.hrdata(sdbits-1 downto 0) := sdi.data(sdbits-1 downto 0);
194 else
195 v.hrdata((sdbits*2)-1 downto sdbits) := sdi.data(sdbits-1 downto 0);
196 end if;
197 else
198 v.hrdata(sdbits-1 downto sdbits-32) := sdi.data(sdbits-1 downto sdbits-32);
199 v.hrdata(31 downto 0) := sdi.data(31 downto 0);
200 end if;
201 hwdata := ahbreadword(ahbsi.hwdata, r.haddr(4 downto 2)); v.hwdata := hwdata;
202 lline := not r.cfg.casdel & r.cfg.casdel & r.cfg.casdel;
203 if (pageburst = 0) or ((pageburst = 2) and r.cfg.pageburst = '0') then
204 lineburst := true;
205 else lineburst := false; end if;
206
207
208 if ((ahbsi.hready and ahbsi.hsel(hindex)) = '1') then
209 v.size := ahbsi.hsize(1 downto 0); v.hwrite := ahbsi.hwrite;
210 v.htrans := ahbsi.htrans;
211 if ahbsi.htrans(1) = '1' then
212 v.hio := ahbsi.hmbsel(1);
213 v.hsel := '1'; v.hready := v.hio;
214 end if;
215 v.haddr := ahbsi.haddr;
216 -- addr must be masked since address range can be smaller than
217 -- total banksize. this can result in wrong chip select being
218 -- asserted
219 for i in 31 downto 20 loop
220 v.haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
221 end loop;
222 end if;
223
224 if (r.hsel = '1') and (ahbsi.hready = '0') then
225 haddr := r.haddr; hsize := r.size;
226 htrans := r.htrans; hwrite := r.hwrite;
227 else
228 haddr := ahbsi.haddr; hsize := ahbsi.hsize(1 downto 0);
229 htrans := ahbsi.htrans; hwrite := ahbsi.hwrite;
230 -- addr must be masked since address range can be smaller than
231 -- total banksize. this can result in wrong chip select being
232 -- asserted
233 for i in 31 downto 20 loop
234 haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
235 end loop;
236 end if;
237 if fast = 1 then haddr := r.haddr; end if;
238
239 if ahbsi.hready = '1' then v.hsel := ahbsi.hsel(hindex); end if;
240
241 -- main state
242 if BUS16 then
243 case r.size is
244 when "00" => --bytesize
245 case r.haddr(0) is
246 when '0' => dqm := "11111101";
247 when others => dqm := "11111110";
248 end case;
249 when others => dqm := "11111100"; --halfword, word
250 end case;
251 else
252 case r.size is
253 when "00" =>
254 case r.haddr(1 downto 0) is
255 when "00" => dqm := "11110111";
256 when "01" => dqm := "11111011";
257 when "10" => dqm := "11111101";
258 when others => dqm := "11111110";
259 end case;
260 when "01" =>
261 if r.haddr(1) = '0' then dqm := "11110011"; else dqm := "11111100"; end if;
262 when others => dqm := "11110000";
263 end case;
264 end if;
265 --
266 -- case r.size is
267 -- when "00" =>
268 -- case r.haddr(1 downto 0) is
269 -- when "00" => dqm := "11111101"; lhw := '0'; --lhv := r.haddr(1)
270 -- when "01" => dqm := "11111110"; lhw := '0';
271 -- when "10" => dqm := "11111101"; lhw := '1';
272 -- when others => dqm := "11111110"; lhw := '1';
273 -- end case;
274 -- when "01" =>
275 -- dqm := "11111100";
276 -- if r.haddr(1) = '0' then
277 -- lhw := '0';
278 -- else
279 -- lhw := '1';
280 -- end if;
281 -- when others => dqm := "11111100"; --remember when word: lhw first 0 then 1
282 -- end case;
283 --
284 if BUS64 and (r.bsel = '1') then dqm := dqm(3 downto 0) & "1111"; end if;
285
286 -- main FSM
287
288 case r.mstate is
289 when midle =>
290 if ((v.hsel and htrans(1) and not v.hio) = '1') then
291 if (r.sdstate = sidle) and (r.cfg.command = "000")
292 and (r.cmstate = midle) and (v.hio = '0')
293 then
294 if fast = 0 then startsd := '1'; else v.startsd := '1'; end if;
295 v.mstate := active;
296 elsif ((r.sdstate = sref) or (r.sdstate = pd) or (r.sdstate = dpd))
297 and (r.cfg.command = "000") and (r.cmstate = midle) and (v.hio = '0')
298 then
299 v.startsd := '1';
300 if r.sdstate = dpd then -- Error response when on Deep Power-Down mode
301 v.hresp := HRESP_ERROR;
302 else
303 v.mstate := active;
304 end if;
305 end if;
306 end if;
307 when others => null;
308 end case;
309
310 startsd := startsd or r.startsd;
311
312 -- generate row and column address size
313
314 if BUS16 then
315 case r.cfg.csize is
316 when "00" => raddr := haddr(21 downto 9);-- case to check for bursting over row limit, since 1 row is 512 byte.
317 when "01" => raddr := haddr(22 downto 10);
318 when "10" => raddr := haddr(23 downto 11);
319 when others =>
320 if r.cfg.bsize = "110" then raddr := haddr(25 downto 13); --tänk
321 else raddr := haddr(24 downto 12); end if;
322 end case;
323 else
324 case r.cfg.csize is
325 when "00" => raddr := haddr(22 downto 10);
326 when "01" => raddr := haddr(23 downto 11);
327 when "10" => raddr := haddr(24 downto 12);
328 when others =>
329 if r.cfg.bsize = "111" then raddr := haddr(26 downto 14);
330 else raddr := haddr(25 downto 13); end if;
331 end case;
332 end if;
333
334 -- generate bank address
335 -- if BUS16 then --011
336 -- ba := genmux(r.cfg.bsize, haddr(26 downto 19)) &
337 -- genmux(r.cfg.bsize, haddr(25 downto 18));
338 -- else
339 ba := genmux(r.cfg.bsize, haddr(28 downto 21)) &
340 genmux(r.cfg.bsize, haddr(27 downto 20));
341 -- end if;
342
343 -- generate chip select
344
345 if BUS64 then
346 adec := genmux(r.cfg.bsize, haddr(30 downto 23));
347 v.bsel := genmux(r.cfg.bsize, r.haddr(29 downto 22));
348 else
349 adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
350 end if;
351 -- elsif BUS32 then
352 -- adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
353 -- else
354 -- adec := genmux(r.cfg.bsize, haddr(27 downto 20)); v.bsel := '0';
355 -- end if;
356
357 rams := adec & not adec;
358
359 -- sdram access FSM
360
361 if r.trfc /= "0000" then v.trfc := r.trfc - 1; end if;
362
363 if r.idlecnt /= "0000" then v.idlecnt := r.idlecnt - 1; end if;
364
365 case r.sdstate is
366
367 when sidle =>
368 if (startsd = '1') and (r.cfg.command = "000") and (r.cmstate = midle) then
369 -- if BUS16 then
370 -- v.address(16 downto 2) := '0' & ba & raddr(11 downto 0); --since 1 bit lower row => tot adress field 14 bits
371 -- else
372 v.address(16 downto 2) := ba & raddr; -- ba(16-15) & raddr(14-2) (2+13= 15 bits)
373 -- end if;
374 v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1;
375 v.startsd := '0';
376 elsif (r.idlecnt = "0000") and (r.cfg.command = "000")
377 and (r.cmstate = midle) and (r.cfg.mobileen(1) = '1') then
378 case r.cfg.pmode is
379 when PM_SR =>
380 v.cfg.cke := '0'; v.sdstate := sref;
381 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
382 v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc; -- Control minimum duration of Self Refresh mode (= tRAS)
383 when PM_PD => v.cfg.cke := '0'; v.sdstate := pd;
384 when PM_DPD =>
385 v.cfg.cke := '0'; v.sdstate := dpd;
386 v.sdcsn := (others => '0'); v.sdwen := '0'; v.rasn := '1'; v.casn := '1';
387 when others =>
388 end case;
389 end if;
390
391 when act1 =>
392 v.rasn := '1'; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
393 if r.cfg.casdel = '1' then v.sdstate := act2; else
394 v.sdstate := act3;
395 if not BUS16 then -- needs if, otherwise it might clock in incorrect write data to state act3_16
396 v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
397 end if;
398 end if;
399 if WPROTEN then
400 v.wprothit := sdi.wprot;
401 if sdi.wprot = '1' then v.hresp := HRESP_ERROR; end if;
402 end if;
403
404 when act2 =>
405 v.sdstate := act3;
406 if not BUS16 then
407 v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
408 end if;
409 if WPROTEN and (r.wprothit = '1') then
410 v.hresp := HRESP_ERROR; v.hready := '0';
411 end if;
412
413 when act3 =>
414 v.casn := '0';
415 if BUS16 then --HW adress needed to memory
416 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 1); --only allowed to use tot adressbits - ba bits
417 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 1); --only allowed to use tot adressbits - ba bits
418 v.lhw := r.haddr(1); -- 14-2 = 12 colummn bits => 13 downto 2
419 else
420 v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
421 end if;
422 v.dqm := dqm; v.burst := r.hready; -- ??
423
424 if r.hwrite = '1' then
425
426 if BUS16 then --16 bit
427 if r.size(1) = '1' then --word
428 v.hready := ahbsi.htrans(0) and ahbsi.htrans(1); --delayed this check 1 state to keep write data correct in act3_16
429 v.burst := ahbsi.htrans(0) and ahbsi.htrans(1);
430 v.sdstate := act3_16; -- goto state for second part of word transfer
431 -- v.lhw := '0'; --write MSB 16 bits to AMBA adress that ends with 00
432 else --halfword or byte
433 v.sdstate := act3_16; v.hready := '1';
434 end if;
435 else --32 bit or 64
436 v.sdstate := wr1;
437 if ahbsi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if;
438 end if;
439 v.sdwen := '0'; v.bdrive := '0'; --write
440 if WPROTEN and (r.wprothit = '1') then
441 v.hresp := HRESP_ERROR; v.hready := '1';
442 if BUS16 then v.sdstate := act3_16; else v.sdstate := wr1; end if;
443 v.sdwen := '1'; v.bdrive := '1'; v.casn := '1'; --skip write, remember hready high in next state
444 end if;
445 else v.sdstate := rd1; end if;
446
447 when act3_16 => --handle 16 bit and WORD write
448 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 2) & '1';
449 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 2) & '1';
450 v.lhw := '1';
451 if (r.hready and r.burst) = '1' and not (WPROTEN and (r.wprothit = '1')) then
452 v.hready := '0'; --kolla på transfertyp nonseq om vi vill delaya nedankoll.
453 if( ahbsi.htrans = "11" and
454 not ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) and
455 not ((r.haddr(9) xor ahbsi.haddr(9)) = '1' and r.cfg.csize = "00") ) then
456 v.sdstate := wr1_16;
457 end if;
458 elsif r.burst = '1' or (r.hready and not r.burst) = '1' then --terminate burst or single write
459 v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
460 v.dqm := (others => '1');
461 else -- complete single write
462 v.hready := '1';
463 v.sdstate := act3_16; --gick till wr1 förut
464 end if;
465
466 when wr1_16 =>
467 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 1);
468 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 1);
469 v.lhw := r.haddr(1);
470 v.sdstate := act3_16;
471 v.hready := '1';
472
473 when wr1 =>
474 v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
475 if (((r.burst and r.hready) = '1') and (r.htrans = "11"))
476 and not (WPROTEN and (r.wprothit = '1'))
477 then
478 v.hready := ahbsi.htrans(0) and ahbsi.htrans(1) and r.hready;
479 if ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) then -- exit on refresh
480 v.hready := '0';
481 end if;
482 else
483 v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
484 v.dqm := (others => '1');
485 end if;
486
487 when wr2 =>
488 if (r.cfg.trp = '0') then v.rasn := '0'; v.sdwen := '0'; end if;
489 v.sdstate := wr3;
490
491 when wr3 =>
492 if (r.cfg.trp = '1') then
493 v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr4;
494 else
495 v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1'; v.sdstate := sidle;
496 v.idlecnt := (others => '1');
497 end if;
498
499 when wr4 =>
500 v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
501 if (r.cfg.trp = '1') then v.sdstate := wr5;
502 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
503
504 when wr5 =>
505 v.sdstate := sidle; v.idlecnt := (others => '1');
506
507 when rd1 => --first read applied to sdram
508 v.casn := '1'; v.sdstate := rd7; --nop
509 if not BUS16 then --starting adress cannot be XXXX...111 since we have word burst in this case. and lowest bit always 0.
510 if lineburst and (ahbsi.htrans = "11") then
511 if r.haddr(4 downto 2) = "111" then
512 v.address(9 downto 5) := r.address(9 downto 5) + 1; --adds only within 1KB limit.
513 v.address(4 downto 2) := "000"; v.casn := '0';
514 end if;
515 end if;
516 end if;
517
518 when rd7 =>
519 v.casn := '1'; --nop
520 if BUS16 then
521 if r.cfg.casdel = '1' then --casdel3
522 v.sdstate := rd2;
523 if lineburst and (ahbsi.htrans = "11") then
524 if r.haddr(3 downto 1) = "110" then
525 v.address(10 downto 5) := r.address(10 downto 5) + 1;
526 v.address(4 downto 2) := "000"; v.casn := '0';
527 end if;
528 end if;
529 else --casdel2
530 v.sdstate := rd3;
531 if ahbsi.htrans /= "11" then
532 if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if;
533 elsif lineburst then
534 if r.haddr(3 downto 1) = "110" then
535 v.address(10 downto 5) := r.address(10 downto 5) + 1;
536 v.address(4 downto 2) := "000"; v.casn := '0';
537 end if;
538 end if;
539 end if;
540 else -- 32 bit or larger
541 if r.cfg.casdel = '1' then --casdel3
542 v.sdstate := rd2;
543 if lineburst and (ahbsi.htrans = "11") then
544 if r.haddr(4 downto 2) = "110" then
545 v.address(9 downto 5) := r.address(9 downto 5) + 1;
546 v.address(4 downto 2) := "000"; v.casn := '0';
547 end if;
548 end if;
549 else --casdel2
550 v.sdstate := rd3;
551 if ahbsi.htrans /= "11" then
552 if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if; --precharge
553 elsif lineburst then
554 if r.haddr(4 downto 2) = "110" then
555 v.address(9 downto 5) := r.address(9 downto 5) + 1;
556 v.address(4 downto 2) := "000"; v.casn := '0';
557 end if;
558 end if;
559 end if;
560 end if;
561
562 when rd2 =>
563 v.casn := '1'; v.sdstate := rd3;
564 if BUS16 then
565 if ahbsi.htrans /= "11" then
566 v.rasn := '0'; v.sdwen := '0'; v.dqm := (others => '1'); --precharge & DQM
567 --note that DQM always has 2 cycle delay before blocking data. So NP if we fetch second HW
568 end if;
569 else
570 if ahbsi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0'; v.dqm := (others => '1'); --precharge & DQM
571 elsif lineburst then
572 if r.haddr(4 downto 2) = "101" then
573 v.address(9 downto 5) := r.address(9 downto 5) + 1;
574 v.address(4 downto 2) := "000"; v.casn := '0';
575 end if;
576 end if;
577 end if;
578
579 when rd3 => --first read data from sdram output v.lhw := r.haddr(1);
580 v.casn := '1'; --if read before cas makes nop else if pre => no difference
581 if BUS16 then
582 --note if read is for halfwor or byte we dont want to read a second time but exit.
583 --if the read is a word we need to change LHW to one since the next read should be muxed in next cylcle.
584 -- if r.size(1) = '1' then --word v.hready := not r.size(1)
585 -- v.sdstate := rd4_16; v.hready := '0'; --hready low since just first part of a word
586 -- v.lhw := '1'; -- read low 16 next state
587 -- else --HW or byte
588 -- v.sdstate := rd4_16; v.hready := '1';
589 -- end if;
590 v.sdstate := rd4_16;
591 v.lhw := not r.lhw; --r.lhw is 0 for word, we should invert for next half of word.For HW or Byte v.lhw does not matter.
592 v.hready := not r.size(1); --if word transfer the r.size(1) is 1 and hready goes low.If HW or byte r.size(1)=0 => hready=1
593 if r.sdwen = '0' then
594 v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); -- make DSEL (NOP)
595 elsif lineburst and ((ahbsi.htrans = "11") and (r.cfg.casdel = '1')) then --only enter if cl3
596 if r.haddr(3 downto 1) = "100" then
597 v.address(10 downto 5) := r.address(10 downto 5) + 1;
598 v.address(4 downto 2) := "000"; v.casn := '0';
599 end if;
600 end if;
601 else --32 bit or larger
602 v.sdstate := rd4; v.hready := '1';
603 if r.sdwen = '0' then
604 v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); -- make DSEL (NOP)
605 elsif lineburst and (ahbsi.htrans = "11") and (r.casn = '1') then
606 if r.haddr(4 downto 2) = ("10" & not r.cfg.casdel) then
607 v.address(9 downto 5) := r.address(9 downto 5) + 1;
608 v.address(4 downto 2) := "000"; v.casn := '0';
609 end if;
610 end if;
611 end if;
612
613 when rd4_16 => --enter as word (r.hready is still 0) else 1. If hready one next transfer sampled into v.
614 --v.hready := '1';
615 v.hready := not r.hready;-- if Byte or HW exit with hready low. If word flip bit, makes correct exit with hready low.
616 v.lhw := not r.lhw; --r.lhw is one the first time we enter (taking care of second part of word)
617 v.casn := '1';
618 --quit on: Single transfer CL 2/3 (prcharge if CL 2 and timer was not 0)
619 if (ahbsi.htrans /= "11" and (r.hready = '1')) or
620 ((r.haddr(9) xor ahbsi.haddr(9)) = '1' and r.cfg.csize = "00" and r.hready = '1') or --probably dont have to check hready 1 since if 0 adresses equal.
621 ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100") and (r.hready = '1')) then --quit on: ST W/HW/BYTE OR
622 --v.hready := '0'; --if Byte or HW exit with hready low, if ST word exit with high.
623 v.dqm := (others => '1');
624 if r.sdcsn /= "11" then --not prechargeing
625 v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5; --precharge
626 else--exit
627 if r.cfg.trp = '1' then v.sdstate := rd6;
628 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
629 end if;
630 elsif lineburst then --NOTE: r.casn = 1 makes sure its the first halfword of a word that is checked (hready low)
631 if r.cfg.casdel = '0' then
632 if (r.haddr(3 downto 1) = "100") and (r.casn = '1') then --lline = 011 if casdel =1, 100 if casdel= 0
633 v.address(10 downto 5) := r.address(10 downto 5) + 1;
634 v.address(4 downto 2) := "000"; v.casn := '0';
635 end if;
636 else
637 if (r.haddr(3 downto 1) = "010") and (r.hready = '1') then --lline = 011 if casdel =1, 100 if casdel= 0
638 v.address(10 downto 5) := r.address(10 downto 5) + 1;
639 v.address(4 downto 2) := "000"; v.casn := '0';
640 end if;
641 end if;
642 end if;
643
644 when rd4 =>
645 v.hready := '1'; v.casn := '1';
646 if (ahbsi.htrans /= "11") or (r.sdcsn = "11") or
647 ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) -- exit on refresh
648 then
649 v.hready := '0'; v.dqm := (others => '1');
650 if (r.sdcsn /= "11") then
651 v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5;
652 else
653 if r.cfg.trp = '1' then v.sdstate := rd6;
654 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
655 end if;
656 elsif lineburst then
657 if (r.haddr(4 downto 2) = lline) and (r.casn = '1') then
658 v.address(9 downto 5) := r.address(9 downto 5) + 1;
659 v.address(4 downto 2) := "000"; v.casn := '0';
660 end if;
661 end if;
662
663 when rd5 =>
664 if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
665 v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := (others => '1');
666 v.casn := '1';
667
668 when rd6 =>
669 v.sdstate := sidle; v.idlecnt := (others => '1'); v.dqm := (others => '1');
670 v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1';
671
672 when sref =>
673 if (startsd = '1' and (r.hio = '0'))
674 or (r.cfg.command /= "000") or r.cfg.pmode /= PM_SR then
675 if r.trfc = "0000" then -- Minimum duration (= tRAS)
676 v.cfg.cke := '1';
677 v.sdcsn := (others => '0'); v.rasn := '1'; v.casn := '1';
678 end if;
679 if r.cfg.cke = '1' then
680 if (r.idlecnt = "0000") then -- tXSR ns with NOP
681 v.sdstate := sidle;
682 v.idlecnt := (others => '1');
683 v.sref_tmpcom := r.cfg.command;
684 v.cfg.command := "100";
685 end if;
686 else
687 v.idlecnt := r.cfg.txsr;
688 end if;
689 end if;
690
691 when pd =>
692 if (startsd = '1' and (r.hio = '0'))
693 or (r.cfg.command /= "000") or r.cfg.pmode /= PM_PD then
694 v.cfg.cke := '1';
695 v.sdstate := sidle;
696 v.idlecnt := (others => '1');
697 end if;
698
699 when dpd =>
700 v.sdcsn := (others => '1'); v.sdwen := '1'; v.rasn := '1'; v.casn := '1';
701 v.cfg.renable := '0';
702 if (startsd = '1' and r.hio = '0') then
703 v.hready := '1'; -- ack all accesses with Error response
704 v.startsd := '0';
705 v.hresp := HRESP_ERROR;
706 elsif r.cfg.pmode /= PM_DPD then
707 v.cfg.cke := '1';
708 if r.cfg.cke = '1' then
709 v.sdstate := sidle;
710 v.idlecnt := (others => '1');
711 v.cfg.renable := '1';
712 end if;
713 end if;
714
715 when others =>
716 v.sdstate := sidle; v.idlecnt := (others => '1');
717 end case;
718
719 -- sdram commands
720
721 case r.cmstate is
722 when midle =>
723 if r.sdstate = sidle then
724 case r.cfg.command is
725 when "010" => -- precharge
726 v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0';
727 v.address(12) := '1'; v.cmstate := active;
728 when "100" => -- auto-refresh
729 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
730 v.cmstate := active;
731 when "110" => -- Lodad Mode Reg
732 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
733 v.sdwen := '0'; v.cmstate := active;
734 if lineburst then
735 v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0011";
736 else
737 v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0111";
738 end if;
739 when "111" => -- Load Ext-Mode Reg
740 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
741 v.sdwen := '0'; v.cmstate := active;
742 v.address(16 downto 2) := "10000000" & r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0)
743 & r.cfg.pasr(2 downto 0);
744 when others => null;
745 end case;
746 end if;
747 when active =>
748 v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1';
749 v.sdwen := '1'; --v.cfg.command := "000";
750 v.cfg.command := r.sref_tmpcom; v.sref_tmpcom := "000";
751 v.cmstate := leadout; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
752 when leadout =>
753 if r.trfc = "0000" then v.cmstate := midle; end if;
754
755 end case;
756
757 -- sdram init
758
759 case r.istate is
760 when iidle =>
761 v.cfg.cke := '1';
762 if r.cfg.renable = '1' and r.cfg.cke = '1' then
763 v.cfg.command := "010"; v.istate := pre;
764 end if;
765 when pre =>
766 if r.cfg.command = "000" then
767 v.cfg.command := "100"; v.istate := ref; v.icnt := "111";
768 end if;
769 when ref =>
770 if r.cfg.command = "000" then
771 v.cfg.command := "100"; v.icnt := r.icnt - 1;
772 if r.icnt = "000" then v.istate := lmode; v.cfg.command := "110"; end if;
773 end if;
774 when lmode =>
775 if r.cfg.command = "000" then
776 if r.cfg.mobileen = "11" then
777 v.cfg.command := "111"; v.istate := emode;
778 else
779 v.istate := finish;
780 end if;
781 end if;
782 when emode =>
783 if r.cfg.command = "000" then
784 v.istate := finish;
785 end if;
786 when others =>
787 if r.cfg.renable = '0' and r.sdstate /= dpd then
788 v.istate := iidle;
789 end if;
790 end case;
791
792 if (ahbsi.hready and ahbsi.hsel(hindex) ) = '1' then
793 if ahbsi.htrans(1) = '0' then v.hready := '1'; end if;
794 end if;
795
796 if (r.hsel and r.hio and not r.hready) = '1' then v.hready := '1'; end if;
797
798 -- second part of main fsm
799
800 case r.mstate is
801 when active =>
802 if v.hready = '1' then
803 v.mstate := midle;
804 end if;
805 when others => null;
806 end case;
807
808 -- sdram refresh counter
809
810 -- pragma translate_off
811 if not is_x(r.cfg.refresh) then
812 -- pragma translate_on
813 if (r.cfg.renable = '1') and (r.istate = finish) and r.sdstate /= sref then
814 v.refresh := r.refresh - 1;
815 if (v.refresh(14) and not r.refresh(14)) = '1' then
816 v.refresh := r.cfg.refresh;
817 v.cfg.command := "100";
818 arefresh := '1';
819 end if;
820 end if;
821 -- pragma translate_off
822 end if;
823 -- pragma translate_on
824
825 -- AHB register access
826 -- if writing to IO space config regs. Just mapping write data to all config values in config reg
827 if (r.hsel and r.hio and r.hwrite and r.htrans(1)) = '1' then
828 if r.haddr(3 downto 2) = "00" then
829 if pageburst = 2 then v.cfg.pageburst := hwdata(17); end if;
830 v.cfg.command := hwdata(20 downto 18);
831 v.cfg.csize := hwdata(22 downto 21);
832 v.cfg.bsize := hwdata(25 downto 23);
833 v.cfg.casdel := hwdata(26);
834 v.cfg.trfc := hwdata(29 downto 27);
835 v.cfg.trp := hwdata(30);
836 v.cfg.renable := hwdata(31);
837 v.cfg.refresh := hwdata(14 downto 0);
838 v.refresh := (others => '0');
839 elsif r.haddr(3 downto 2) = "01" then
840 if r.cfg.mobileen(1) = '1' and mobile /= 3 then v.cfg.mobileen(0) := hwdata(31); end if;
841 if r.cfg.pmode = "000" then
842 v.cfg.cke := hwdata(30);
843 end if;
844 if r.cfg.mobileen(1) = '1' then
845 v.cfg.txsr := hwdata(23 downto 20);
846 v.cfg.pmode := hwdata(18 downto 16);
847 v.cfg.ds(3 downto 2) := hwdata( 6 downto 5);
848 v.cfg.tcsr(3 downto 2) := hwdata( 4 downto 3);
849 v.cfg.pasr(5 downto 3) := hwdata( 2 downto 0);
850 end if;
851 end if;
852 end if;
853
854 -- Disable CS and DPD when Mobile SDR is Disabled
855 if r.cfg.mobileen(0) = '0' then v.cfg.pmode(2) := '0'; end if;
856
857 -- Update EMR when ds, tcsr or pasr change
858 if r.cfg.command = "000" and arefresh = '0' and r.cfg.mobileen(0) = '1' then
859 if r.cfg.ds(1 downto 0) /= r.cfg.ds(3 downto 2) then
860 v.cfg.command := "111"; v.cfg.ds(1 downto 0) := r.cfg.ds(3 downto 2);
861 end if;
862 if r.cfg.tcsr(1 downto 0) /= r.cfg.tcsr(3 downto 2) then
863 v.cfg.command := "111"; v.cfg.tcsr(1 downto 0) := r.cfg.tcsr(3 downto 2);
864 end if;
865 if r.cfg.pasr(2 downto 0) /= r.cfg.pasr(5 downto 3) then
866 v.cfg.command := "111"; v.cfg.pasr(2 downto 0) := r.cfg.pasr(5 downto 3);
867 end if;
868 end if;
869
870 regsd := (others => '0');
871 --reads out config registers (r/w does not matter) according to manual depending on address, notice generic determines data width.
872 if r.haddr(3 downto 2) = "00" then
873 regsd(31 downto 18) := r.cfg.renable & r.cfg.trp & r.cfg.trfc &
874 r.cfg.casdel & r.cfg.bsize & r.cfg.csize & r.cfg.command;
875 if not lineburst then regsd(17) := '1'; end if;
876 regsd(16) := r.cfg.mobileen(1);
877 if BUS64 then regsd(15) := '1'; end if;
878 regsd(14 downto 0) := r.cfg.refresh;
879 elsif r.haddr(3 downto 2) = "01" then
880 regsd(31) := r.cfg.mobileen(0);
881 regsd(30) := r.cfg.cke;
882 regsd(23 downto 0) := r.cfg.txsr & '0' & r.cfg.pmode & "000000000" &
883 r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0) & r.cfg.pasr(2 downto 0);
884 end if;
885
886 if (r.hsel and r.hio) = '1' then dout := regsd;
887 else
888 if BUS64 and r.bsel = '1' then dout := r.hrdata(63 downto 32);
889 else dout := r.hrdata(31 downto 0); end if;
890 end if;
891
892 v.nbdrive := not v.bdrive;
893
894 if oepol = 1 then bdrive := r.nbdrive; vbdrive := (others => v.nbdrive);
895 else bdrive := r.bdrive; vbdrive := (others => v.bdrive);end if;
896
897 -- reset
898
899 if rst = '0' then
900 v.sdstate := sidle;
901 v.mstate := midle;
902 v.istate := iidle;
903 v.cmstate := midle;
904 v.hsel := '0';
905 v.cfg.command := "000";
906 v.cfg.csize := "01";
907 v.cfg.bsize := "011";
908 v.cfg.casdel := '1';
909 v.cfg.trfc := "111";
910 if pwron = 1 then v.cfg.renable := '1';
911 else v.cfg.renable := '0'; end if;
912 v.cfg.trp := '1';
913 v.dqm := (others => '1');
914 v.sdwen := '1';
915 v.rasn := '1';
916 v.casn := '1';
917 v.hready := '1';
918 v.bsel := '0';
919 v.startsd := '0';
920 if (pageburst = 2) then
921 v.cfg.pageburst := '0';
922 end if;
923 if mobile >= 2 then v.cfg.mobileen := "11";
924 elsif mobile = 1 then v.cfg.mobileen := "10";
925 else v.cfg.mobileen := "00"; end if;
926 v.cfg.txsr := (others => '1');
927 v.cfg.pmode := (others => '0');
928 v.cfg.ds := (others => '0');
929 v.cfg.tcsr := (others => '0');
930 v.cfg.pasr := (others => '0');
931 if mobile >= 2 then v.cfg.cke := '0';
932 else v.cfg.cke := '1'; end if;
933 v.sref_tmpcom := "000";
934 v.idlecnt := (others => '1');
935 end if;
936
937 ri <= v;
938 ribdrive <= vbdrive;
939
940 ahbso.hready <= r.hready;
941 ahbso.hresp <= r.hresp;
942 ahbso.hrdata <= ahbdrivedata(dout);
943
944 end process;
945
946 --sdo.sdcke <= (others => '1');
947 sdo.sdcke <= (others => r.cfg.cke);
948 ahbso.hconfig <= hconfig;
949 ahbso.hirq <= (others => '0');
950 ahbso.hindex <= hindex;
951 ahbso.hsplit <= (others => '0');
952
953 -- Quick hack to get rid of undriven signal warnings. Check this for future
954 -- merge with main sdctrl.
955 drivehack : block
956 begin
957 sdo.qdrive <= '0';
958 sdo.nbdrive <= '0';
959 sdo.ce <= '0';
960 sdo.moben <= '0';
961 sdo.cal_rst <= '0';
962 sdo.oct <= '0';
963 sdo.xsdcsn <= (others => '1');
964 sdo.data(127 downto 16) <= (others => '0');
965 sdo.cb <= (others => '0');
966 sdo.ba <= (others => '0');
967 sdo.sdck <= (others => '0');
968 sdo.cal_en <= (others => '0');
969 sdo.cal_inc <= (others => '0');
970 sdo.cal_pll <= (others => '0');
971 sdo.odt <= (others => '0');
972 sdo.conf <= (others => '0');
973 sdo.vcbdrive <= (others => '0');
974 sdo.dqs_gate <= '0';
975 sdo.cbdqm <= (others => '0');
976 sdo.cbcal_en <= (others => '0');
977 sdo.cbcal_inc <= (others => '0');
978 sdo.read_pend <= (others => '0');
979 sdo.regwdata <= (others => '0');
980 sdo.regwrite <= (others => '0');
981 end block drivehack;
982
983 regs : process(clk, rst) begin
984 if rising_edge(clk) then
985 r <= ri; rbdrive <= ribdrive;
986 if rst = '0' then r.icnt <= (others => '0'); end if;
987 end if;
988 if (rst = '0') then
989 r.sdcsn <= (others => '1'); r.bdrive <= '1'; r.nbdrive <= '0';
990 if oepol = 0 then rbdrive <= (others => '1');
991 else rbdrive <= (others => '0'); end if;
992 end if;
993 end process;
994
995 rgen : if not SDINVCLK generate
996 sdo.address <= r.address;
997 sdo.bdrive <= r.nbdrive when oepol = 1 else r.bdrive;
998 sdo.vbdrive <= zero32 & rbdrive;
999 sdo.sdcsn <= r.sdcsn;
1000 sdo.sdwen <= r.sdwen;
1001 sdo.dqm <= "11111111" & r.dqm;
1002 sdo.rasn <= r.rasn;
1003 sdo.casn <= r.casn;
1004
1005 mux16_wrdata : if BUS16 generate --mux data depending on Low/High HW
1006 sdo.data(15 downto 0) <= r.hwdata(15 downto 0) when r.lhw = '1' else r.hwdata(31 downto 16);
1007 end generate;
1008
1009 wrdata : if not BUS16 generate
1010 drivebus: for i in 0 to sdbits/64 generate
1011 sdo.data(31+32*i downto 32*i) <= r.hwdata;
1012 end generate;
1013 end generate;
1014 end generate;
1015
1016 ngen : if SDINVCLK generate
1017 nregs : process(clk, rst) begin
1018 if falling_edge(clk) then
1019 sdo.address <= r.address;
1020 if oepol = 1 then sdo.bdrive <= r.nbdrive;
1021 else sdo.bdrive <= r.bdrive; end if;
1022 sdo.vbdrive <= zero32 & rbdrive;
1023 sdo.sdcsn <= r.sdcsn;
1024 sdo.sdwen <= r.sdwen;
1025 sdo.dqm <= "11111111" & r.dqm;
1026 sdo.rasn <= r.rasn;
1027 sdo.casn <= r.casn;
1028 if BUS16 then --mux data depending on Low/High HW
1029 if (r.lhw ='1') then
1030 sdo.data(15 downto 0) <= r.hwdata(15 downto 0);
1031 else
1032 sdo.data(15 downto 0) <= r.hwdata(31 downto 16);
1033 end if;
1034 end if;
1035
1036 if not BUS16 then
1037 for i in 0 to sdbits/64 loop
1038 sdo.data(31+32*i downto 32*i) <= r.hwdata;
1039 end loop;
1040 end if;
1041 end if;
1042 if rst = '0' then sdo.sdcsn <= (others => '1'); end if;
1043 end process;
1044 end generate;
1045
1046 -- pragma translate_off
1047 bootmsg : report_version
1048 generic map ("sdctrl16" & tost(hindex) &
1049 ": PC133 SDRAM controller rev " & tost(REVISION));
1050 -- pragma translate_on
1051
1052 end;
1053
@@ -0,0 +1,200
1 ------------------------------------------------------------------------------
2 -- LEON3 Demonstration design test bench
3 -- Copyright (C) 2004 Jiri Gaisler, Gaisler Research
4 ------------------------------------------------------------------------------
5 ------------------------------------------------------------------------------
6 -- This file is a part of the GRLIB VHDL IP LIBRARY
7 -- Copyright (C) 2003 - 2008, Gaisler Research
8 -- Copyright (C) 2008 - 2014, Aeroflex Gaisler
9 -- Copyright (C) 2015 - 2016, Cobham Gaisler
10 --
11 -- This program is free software; you can redistribute it and/or modify
12 -- it under the terms of the GNU General Public License as published by
13 -- the Free Software Foundation; either version 2 of the License, or
14 -- (at your option) any later version.
15 --
16 -- This program is distributed in the hope that it will be useful,
17 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
18 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 -- GNU General Public License for more details.
20 --
21 -- You should have received a copy of the GNU General Public License
22 -- along with this program; if not, write to the Free Software
23 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25 library ieee;
26 use ieee.std_logic_1164.all;
27 library gaisler;
28 use gaisler.libdcom.all;
29 use gaisler.sim.all;
30 use work.debug.all;
31 library techmap;
32 use techmap.gencomp.all;
33 library micron;
34 use micron.components.all;
35 library grlib;
36 use grlib.stdlib.all;
37
38 use work.config.all; -- configuration
39
40
41 entity testbench is
42 generic (
43 fabtech : integer := CFG_FABTECH;
44 memtech : integer := CFG_MEMTECH;
45 padtech : integer := CFG_PADTECH;
46 clktech : integer := CFG_CLKTECH;
47 disas : integer := CFG_DISAS; -- Enable disassembly to console
48 dbguart : integer := CFG_DUART; -- Print UART on console
49 pclow : integer := CFG_PCLOW;
50
51 clkperiod : integer := 20; -- system clock period
52 romdepth : integer := 22 -- rom address depth (flash 4 MB)
53 -- sramwidth : integer := 32; -- ram data width (8/16/32)
54 -- sramdepth : integer := 20; -- ram address depth
55 -- srambanks : integer := 2 -- number of ram banks
56 );
57 end;
58
59 architecture behav of testbench is
60
61 constant promfile : string := "prom.srec"; -- rom contents
62 constant sramfile : string := "ram.srec"; -- ram contents
63 constant sdramfile : string := "ram.srec"; -- sdram contents
64
65
66 signal SW : std_logic_vector(4 downto 1);
67 signal clk : std_logic := '0';
68 signal Rst : std_logic := '0'; -- Reset
69 constant ct : integer := clkperiod/2;
70
71 signal address : std_logic_vector(21 downto 0);
72 signal data : std_logic_vector(31 downto 24);
73
74 signal romsn : std_logic;
75 signal oen : std_logic;
76 signal writen : std_logic;
77 signal dsuen, dsutx, dsurx, dsubre, dsuact : std_logic;
78 signal dsurst : std_logic;
79 signal error : std_logic;
80
81 signal sdcke : std_logic;
82 signal sdcsn : std_logic;
83 signal sdwen : std_logic; -- write en
84 signal sdrasn : std_logic; -- row addr stb
85 signal sdcasn : std_logic; -- col addr stb
86 signal dram_ldqm : std_logic;
87 signal dram_udqm : std_logic;
88 signal sdclk : std_logic;
89 signal dram_ba : std_logic_vector(1 downto 0);
90
91
92
93 constant lresp : boolean := false;
94
95
96 signal sa : std_logic_vector(12 downto 0);
97 signal sd : std_logic_vector(15 downto 0);
98
99
100 begin
101
102 clk <= not clk after ct * 1 ns; --50 MHz clk
103 rst <= dsurst; --reset
104 dsuen <= '1';
105 dsubre <= '1'; -- inverted on the board
106 sw(1) <= rst;
107
108 d3 : entity work.leon3mp
109 generic map ( fabtech, memtech, padtech, clktech, disas, dbguart, pclow )
110 port map (
111 CLK50 => clk,
112 LEDS => open,
113 SW => SW,
114 dram_addr => sa,
115 dram_ba_0 => dram_ba(0),
116 dram_ba_1 => dram_ba(1),
117 dram_dq => sd(15 downto 0),
118 dram_clk => sdclk,
119 dram_cke => sdcke,
120 dram_cs_n => sdcsn,
121 dram_we_n => sdwen,
122 dram_ras_n => sdrasn,
123 dram_cas_n => sdcasn,
124 dram_ldqm => dram_ldqm,
125 dram_udqm => dram_udqm,
126 uart_txd => dsutx,
127 uart_rxd => dsurx);
128
129 u1: entity work.mt48lc16m16a2 generic map (addr_bits => 13, col_bits => 9, index => 1024, fname => sdramfile)
130 PORT MAP(
131 Dq => sd(15 downto 0), Addr => sa(12 downto 0),
132 Ba => dram_ba, Clk => sdclk, Cke => sdcke,
133 Cs_n => sdcsn, Ras_n => sdrasn, Cas_n => sdcasn, We_n => sdwen,
134 Dqm(0) => dram_ldqm, Dqm(1) => dram_udqm );
135
136
137
138 error <= 'H'; -- ERROR pull-up
139
140 iuerr : process
141 begin
142 wait for 2500 ns;
143 if to_x01(error) = '1' then wait on error; end if;
144 assert (to_x01(error) = '1')
145 report "*** IU in error mode, simulation halted ***"
146 severity failure ;
147 end process;
148
149 data <= buskeep(data) after 5 ns;
150 sd <= buskeep(sd) after 5 ns;
151
152 dsucom : process
153 variable w32 : std_logic_vector(31 downto 0);
154 constant txp : time := 160 * 1 ns;
155 procedure writeReg(signal dsutx : out std_logic; address : integer; value : integer) is
156 begin
157 txc(dsutx, 16#c0#, txp); --control byte
158 txa(dsutx, (address / (256*256*256)) , (address / (256*256)), (address / (256)), address, txp); --adress
159 txa(dsutx, (value / (256*256*256)) , (value / (256*256)), (value / (256)), value, txp); --write data
160 end;
161
162 procedure readReg(signal dsurx : in std_logic; signal dsutx : out std_logic; address : integer; value: out std_logic_vector) is
163
164 begin
165 txc(dsutx, 16#a0#, txp); --control byte
166 txa(dsutx, (address / (256*256*256)) , (address / (256*256)), (address / (256)), address, txp); --adress
167 rxi(dsurx, value, txp, lresp); --write data
168 end;
169
170 procedure dsucfg(signal dsurx : in std_logic; signal dsutx : out std_logic) is
171 variable c8 : std_logic_vector(7 downto 0);
172 begin
173 dsutx <= '1';
174 dsurst <= '0'; --reset low
175 wait for 500 ns;
176 dsurst <= '1'; --reset high
177 --wait; --evig w8
178 wait for 5000 ns;
179 txc(dsutx, 16#55#, txp);
180 --dsucfg(dsutx, dsurx);
181 writeReg(dsutx,16#40000000#,16#12345678#);
182 writeReg(dsutx,16#40000004#,16#22222222#);
183 writeReg(dsutx,16#40000008#,16#33333333#);
184 writeReg(dsutx,16#4000000C#,16#44444444#);
185
186 readReg(dsurx,dsutx,16#40000000#,w32);
187 readReg(dsurx,dsutx,16#40000004#,w32);
188 readReg(dsurx,dsutx,16#40000008#,w32);
189 readReg(dsurx,dsutx,16#4000000C#,w32);
190
191 end;
192
193 begin
194 dsucfg(dsutx, dsurx);
195
196
197 wait;
198 end process;
199 end ;
200
@@ -0,0 +1,143
1 # Clocks
2 NET "CLK50" PERIOD = 20 ns |LOC = "K3";
3 #NET "CLK32" PERIOD = 31.25 ns | LOC = "J4";
4 # LEDs
5 NET "LEDS<0>" LOC="P11" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
6 NET "LEDS<1>" LOC="N9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
7 NET "LEDS<2>" LOC="M9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
8 NET "LEDS<3>" LOC="P9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
9 NET "LEDS<4>" LOC="T8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
10 NET "LEDS<5>" LOC="N8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
11 NET "LEDS<6>" LOC="P8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
12 NET "LEDS<7>" LOC="P7" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
13
14 # DIP Switches
15 NET "SW<1>" LOC="L1" |IOSTANDARD=LVTTL |PULLUP;
16 NET "SW<2>" LOC="L3" |IOSTANDARD=LVTTL |PULLUP;
17 NET "SW<3>" LOC="L4" |IOSTANDARD=LVTTL |PULLUP;
18 NET "SW<4>" LOC="L5" |IOSTANDARD=LVTTL |PULLUP;
19
20 NET "uart_rxd" LOC="M7" |IOSTANDARD=LVTTL;
21 NET "uart_txd" LOC="N6" |IOSTANDARD=LVTTL;
22
23 # SDRAM
24 NET "dram_udqm" LOC="F15" |IOSTANDARD=LVTTL;
25 NET "dram_clk" LOC="G16" |IOSTANDARD=LVTTL;
26 NET "dram_cke" LOC="H16" |IOSTANDARD=LVTTL;
27 NET "dram_ba_1" LOC="T14" |IOSTANDARD=LVTTL;
28 NET "dram_ba_0" LOC="R14" |IOSTANDARD=LVTTL;
29 NET "dram_cs_n" LOC="R1" |IOSTANDARD=LVTTL;
30 NET "dram_ras_n" LOC="R2" |IOSTANDARD=LVTTL;
31 NET "dram_cas_n" LOC="T4" |IOSTANDARD=LVTTL;
32 NET "dram_we_n" LOC="R5" |IOSTANDARD=LVTTL;
33 NET "dram_ldqm" LOC="T5" |IOSTANDARD=LVTTL;
34 NET "dram_addr<0>" LOC="T15" |IOSTANDARD=LVTTL;
35 NET "dram_addr<1>" LOC="R16" |IOSTANDARD=LVTTL;
36 NET "dram_addr<2>" LOC="P15" |IOSTANDARD=LVTTL;
37 NET "dram_addr<3>" LOC="P16" |IOSTANDARD=LVTTL;
38 NET "dram_addr<4>" LOC="N16" |IOSTANDARD=LVTTL;
39 NET "dram_addr<5>" LOC="M15" |IOSTANDARD=LVTTL;
40 NET "dram_addr<6>" LOC="M16" |IOSTANDARD=LVTTL;
41 NET "dram_addr<7>" LOC="L16" |IOSTANDARD=LVTTL;
42 NET "dram_addr<8>" LOC="K15" |IOSTANDARD=LVTTL;
43 NET "dram_addr<9>" LOC="K16" |IOSTANDARD=LVTTL;
44 NET "dram_addr<10>" LOC="R15" |IOSTANDARD=LVTTL;
45 NET "dram_addr<11>" LOC="J16" |IOSTANDARD=LVTTL;
46 NET "dram_addr<12>" LOC="H15" |IOSTANDARD=LVTTL;
47 NET "dram_dq<0>" LOC="T13" |IOSTANDARD=LVTTL;
48 NET "dram_dq<1>" LOC="T12" |IOSTANDARD=LVTTL;
49 NET "dram_dq<2>" LOC="R12" |IOSTANDARD=LVTTL;
50 NET "dram_dq<3>" LOC="T9" |IOSTANDARD=LVTTL;
51 NET "dram_dq<4>" LOC="R9" |IOSTANDARD=LVTTL;
52 NET "dram_dq<5>" LOC="T7" |IOSTANDARD=LVTTL;
53 NET "dram_dq<6>" LOC="R7" |IOSTANDARD=LVTTL;
54 NET "dram_dq<7>" LOC="T6" |IOSTANDARD=LVTTL;
55 NET "dram_dq<8>" LOC="F16" |IOSTANDARD=LVTTL;
56 NET "dram_dq<9>" LOC="E15" |IOSTANDARD=LVTTL;
57 NET "dram_dq<10>" LOC="E16" |IOSTANDARD=LVTTL;
58 NET "dram_dq<11>" LOC="D16" |IOSTANDARD=LVTTL;
59 NET "dram_dq<12>" LOC="B16" |IOSTANDARD=LVTTL;
60 NET "dram_dq<13>" LOC="B15" |IOSTANDARD=LVTTL;
61 NET "dram_dq<14>" LOC="C16" |IOSTANDARD=LVTTL;
62 NET "dram_dq<15>" LOC="C15" |IOSTANDARD=LVTTL;
63 #Created by Constraints Editor (xc6slx25-ftg256-3) - 2016/12/08
64 INST "dram_addr(0)" TNM = dram_addr;
65 INST "dram_addr(1)" TNM = dram_addr;
66 INST "dram_addr(2)" TNM = dram_addr;
67 INST "dram_addr(3)" TNM = dram_addr;
68 INST "dram_addr(4)" TNM = dram_addr;
69 INST "dram_addr(5)" TNM = dram_addr;
70 INST "dram_addr(6)" TNM = dram_addr;
71 INST "dram_addr(7)" TNM = dram_addr;
72 INST "dram_addr(8)" TNM = dram_addr;
73 INST "dram_addr(9)" TNM = dram_addr;
74 INST "dram_addr(10)" TNM = dram_addr;
75 INST "dram_addr(11)" TNM = dram_addr;
76 INST "dram_addr(12)" TNM = dram_addr;
77 INST "dram_addr(0)" TNM = dram_out;
78 INST "dram_addr(1)" TNM = dram_out;
79 INST "dram_addr(2)" TNM = dram_out;
80 INST "dram_addr(3)" TNM = dram_out;
81 INST "dram_addr(4)" TNM = dram_out;
82 INST "dram_addr(5)" TNM = dram_out;
83 INST "dram_addr(6)" TNM = dram_out;
84 INST "dram_addr(7)" TNM = dram_out;
85 INST "dram_addr(8)" TNM = dram_out;
86 INST "dram_addr(9)" TNM = dram_out;
87 INST "dram_addr(10)" TNM = dram_out;
88 INST "dram_addr(11)" TNM = dram_out;
89 INST "dram_addr(12)" TNM = dram_out;
90 INST "dram_ba_0" TNM = dram_out;
91 INST "dram_ba_1" TNM = dram_out;
92 INST "dram_cas_n" TNM = dram_out;
93 INST "dram_cke" TNM = dram_out;
94 #INST "dram_clk" TNM = dram_out;
95 INST "dram_cs_n" TNM = dram_out;
96 INST "dram_dq(0)" TNM = dram_out;
97 INST "dram_dq(1)" TNM = dram_out;
98 INST "dram_dq(2)" TNM = dram_out;
99 INST "dram_dq(3)" TNM = dram_out;
100 INST "dram_dq(4)" TNM = dram_out;
101 INST "dram_dq(5)" TNM = dram_out;
102 INST "dram_dq(6)" TNM = dram_out;
103 INST "dram_dq(7)" TNM = dram_out;
104 INST "dram_dq(8)" TNM = dram_out;
105 INST "dram_dq(9)" TNM = dram_out;
106 INST "dram_dq(10)" TNM = dram_out;
107 INST "dram_dq(11)" TNM = dram_out;
108 INST "dram_dq(12)" TNM = dram_out;
109 INST "dram_dq(13)" TNM = dram_out;
110 INST "dram_dq(14)" TNM = dram_out;
111 INST "dram_dq(15)" TNM = dram_out;
112 INST "dram_ldqm" TNM = dram_out;
113 INST "dram_ras_n" TNM = dram_out;
114 INST "dram_udqm" TNM = dram_out;
115 INST "dram_we_n" TNM = dram_out;
116 TIMEGRP "dram_out" OFFSET = OUT 12 ns AFTER "CLK50";
117 INST "dram_dq(0)" TNM = dram_in;
118 INST "dram_dq(1)" TNM = dram_in;
119 INST "dram_dq(2)" TNM = dram_in;
120 INST "dram_dq(3)" TNM = dram_in;
121 INST "dram_dq(4)" TNM = dram_in;
122 INST "dram_dq(5)" TNM = dram_in;
123 INST "dram_dq(6)" TNM = dram_in;
124 INST "dram_dq(7)" TNM = dram_in;
125 INST "dram_dq(8)" TNM = dram_in;
126 INST "dram_dq(9)" TNM = dram_in;
127 INST "dram_dq(10)" TNM = dram_in;
128 INST "dram_dq(11)" TNM = dram_in;
129 INST "dram_dq(12)" TNM = dram_in;
130 INST "dram_dq(13)" TNM = dram_in;
131 INST "dram_dq(14)" TNM = dram_in;
132 INST "dram_dq(15)" TNM = dram_in;
133 TIMEGRP "dram_in" OFFSET = IN 3 ns BEFORE "CLK50" RISING;
134
135
136 NET "spw_rxdp" LOC = "h2";# | IOSTANDARD = LVDS_33;
137 NET "spw_rxdn" LOC = "h1";# | IOSTANDARD = LVDS_33;
138 NET "spw_rxsp" LOC = "f4";# | IOSTANDARD = LVDS_33;
139 NET "spw_rxsn" LOC = "f3";# | IOSTANDARD = LVDS_33;
140 NET "spw_txdp" LOC = "e2";# | IOSTANDARD = LVTTL;
141 NET "spw_txdn" LOC = "e1";# | IOSTANDARD = LVTTL;
142 NET "spw_txsp" LOC = "g3";# | IOSTANDARD = LVTTL;
143 NET "spw_txsn" LOC = "g1";# | IOSTANDARD = LVTTL;
@@ -0,0 +1,77
1 VHDLIB=../..
2 SELFDIR := $(dir $(lastword $(MAKEFILE_LIST)))
3 SCRIPTSDIR=$(VHDLIB)/scripts/
4 GRLIB := $(shell sh $(VHDLIB)/scripts/lpp_relpath.sh)
5 TOP=leon3mp
6 BOARD=MiniSpartan6p
7 DESIGN=leon3-MiniSpartan6p
8 include $(VHDLIB)/boards/$(BOARD)/Makefile.inc
9 DEVICE=$(PART)-$(PACKAGE)$(SPEED)
10 UCF=withSPW.ucf
11 UCF_PLANAHEAD=$(UCF)
12 QSF=$(GRLIB)/boards/$(BOARD)/$(TOP).qsf
13 EFFORT=high
14 XSTOPT=-uc leon3mp.xcf
15 SYNPOPT="set_option -pipe 1; set_option -retiming 1; set_option -write_apr_constraint 0"
16
17
18 VHDLOPTSYNFILES = sdctrl16.vhd config.vhd leon3mp.vhd
19
20 VHDLSIMFILES=mt48lc16m16a2.vhd testbench.vhd
21
22 SIMTOP=testbench
23 SDCFILE=$(GRLIB)/boards/$(BOARD)/default.sdc
24 BITGEN=$(VHDLIB)/boards/$(BOARD)/default.ut
25
26 TECHLIBS = unisim
27
28 LIBSKIP = core1553bbc core1553brm core1553brt gr1553 corePCIF \
29 tmtc openchip hynix ihp gleichmann usbhc fmf ftlib gsi
30
31 DIRSKIP = b1553 pcif leon2 leon2ft crypto satcan ddr usb ata i2c \
32 pci grusbhc haps slink ascs can pwm greth coremp7 ac97 atf \
33 grlfpc \
34 ./dsp/lpp_fft_rtax \
35 ./amba_lcd_16x2_ctrlr \
36 ./general_purpose/lpp_AMR \
37 ./general_purpose/lpp_balise \
38 ./general_purpose/lpp_delay \
39 ./lpp_bootloader \
40 ./lpp_sim/CY7C1061DV33 \
41 ./lpp_uart \
42 ./lpp_usb \
43 ./dsp/lpp_fft \
44 ./lpp_leon3_soc \
45 ./lpp_debug_lfr
46
47 FILESKIP = i2cmst.vhd \
48 APB_MULTI_DIODE.vhd \
49 APB_MULTI_DIODE.vhd \
50 Top_MatrixSpec.vhd \
51 APB_FFT.vhd \
52 lpp_lfr_ms_FFT.vhd \
53 lpp_lfr_apbreg.vhd \
54 CoreFFT.vhd \
55 lpp_lfr_ms.vhd \
56 lpp_lfr_sim_pkg.vhd \
57 mtie_maps.vhd \
58 ftsrctrlc.vhd \
59 ftsdctrl.vhd \
60 ftsrctrl8.vhd \
61 ftmctrl.vhd \
62 ftsdctrl64.vhd \
63 ftahbram.vhd \
64 ftahbram2.vhd \
65 sramft.vhd \
66 nandfctrlx.vhd
67
68 include $(GRLIB)/bin/Makefile
69
70 ################## project specific targets ##########################
71
72 load-ram:
73 xc3sprog -c ftdi -p0 leon3mp.bit
74
75 load-flash:
76 xc3sprog -c ftdi -p0 $(VHDLIB)/boards/$(BOARD)/bscan_spi_s6lx25_ftg256.bit
77 xc3sprog -c ftdi -I leon3mp.bit
@@ -0,0 +1,66
1 This LEON3 design is tailored to the Scarab Hardware [MiniSpartan6+](https://www.scarabhardware.com/minispartan6/) board.
2
3 Simulation and synthesis
4 ------------------------
5
6 This design tries to use as much as possible free (as in freedom) tools and at least free (as in free beer) when impossible.
7
8
9 Note that the simulation doesn't work as expected yet.
10
11
12 To build the design:
13 ```bash
14 make ise
15 ```
16
17 To load into FPGA RAM:
18 ```bash
19 make load-ram
20 ```
21
22 To load into FPGA Flash:
23 ```bash
24 make load-flash
25 ```
26
27 Design specifics
28 ----------------
29
30 * The AHB and processor is clocked from the 50 MHz clock.
31
32 * The SDRAM is working with the sdctrl16 memory controller taken from leon3-altera-de2-ep2c35 design.
33
34 * The UART DSU interface ie enabled and connected to interface B of ft2232H chip.
35 Start GRMON with -uart /dev/ttyUSB1
36
37 * Output from GRMON2 should look similar to this:
38
39 ```bash
40 GRMON2 LEON debug monitor v2.0.80-beta 64-bit eval version
41
42 Copyright (C) 2016 Cobham Gaisler - All rights reserved.
43 For latest updates, go to http://www.gaisler.com/
44 Comments or bug-reports to support@gaisler.com
45
46 This eval version will expire on 18/04/2017
47
48 using port /dev/ttyUSB1 @ 115200 baud
49 GRLIB build version: 4164
50 Detected frequency: 50 MHz
51
52 Component Vendor
53 LEON3 SPARC V8 Processor Cobham Gaisler
54 AHB Debug UART Cobham Gaisler
55 AHB/APB Bridge Cobham Gaisler
56 LEON3 Debug Support Unit Cobham Gaisler
57 PC133 SDRAM Controller Cobham Gaisler
58 Multi-processor Interrupt Ctrl. Cobham Gaisler
59 Modular Timer Unit Cobham Gaisler
60 General Purpose I/O port Cobham Gaisler
61
62 Use command 'info sys' to print a detailed report of attached cores
63
64 grmon2>
65
66 ``` No newline at end of file
@@ -0,0 +1,11
1 F0 -> L46P -> DOUT+ -> 9 -> Grey
2 F1 -> L46N -> DOUT- -> 5 -> Yellow
3
4 F5 -> L40P -> SOUT+ -> 8 -> Violet
5 F7 -> L40N -> SOUT- -> 4 -> Orange
6
7 F3 -> L53P -> SIN+ -> 2 -> Brown
8 F6 -> L53N -> SIN- -> 7 -> Blue
9
10 F9 -> L39N -> DIN- -> 6 -> Green
11 F10 -> L39P -> DIN+ -> 1 -> Black
@@ -0,0 +1,162
1
2
3
4 -----------------------------------------------------------------------------
5 -- LEON3 Demonstration design test bench configuration
6 -- Copyright (C) 2009 Aeroflex Gaisler
7 ------------------------------------------------------------------------------
8
9
10 library techmap;
11 use techmap.gencomp.all;
12
13 package config is
14 -- Technology and synthesis options
15 constant CFG_FABTECH : integer := spartan6;
16 constant CFG_MEMTECH : integer := spartan6;
17 constant CFG_PADTECH : integer := spartan6;
18 constant CFG_TRANSTECH : integer := GTP0;
19 constant CFG_NOASYNC : integer := 0;
20 constant CFG_SCAN : integer := 0;
21 -- Clock generator
22 constant CFG_CLKTECH : integer := spartan6;
23 constant CFG_CLKMUL : integer := (3);
24 constant CFG_CLKDIV : integer := (2);
25 constant CFG_OCLKDIV : integer := 1;
26 constant CFG_OCLKBDIV : integer := 0;
27 constant CFG_OCLKCDIV : integer := 0;
28 constant CFG_PCIDLL : integer := 0;
29 constant CFG_PCISYSCLK: integer := 0;
30 constant CFG_CLK_NOFB : integer := 0;
31 -- LEON3 processor core
32 constant CFG_LEON3 : integer := 1;
33 constant CFG_NCPU : integer := (1);
34 constant CFG_NWIN : integer := (8);
35 constant CFG_V8 : integer := 2 + 4*0;
36 constant CFG_MAC : integer := 0;
37 constant CFG_BP : integer := 1;
38 constant CFG_SVT : integer := 1;
39 constant CFG_RSTADDR : integer := 16#00000#;
40 constant CFG_LDDEL : integer := (2);
41 constant CFG_NOTAG : integer := 1;
42 constant CFG_NWP : integer := (0);
43 constant CFG_PWD : integer := 0*2;
44 constant CFG_FPU : integer := 0 + 16*0 + 32*0;
45 constant CFG_GRFPUSH : integer := 0;
46 constant CFG_ICEN : integer := 1;
47 constant CFG_ISETS : integer := 1;
48 constant CFG_ISETSZ : integer := 8;
49 constant CFG_ILINE : integer := 8;
50 constant CFG_IREPL : integer := 0;
51 constant CFG_ILOCK : integer := 0;
52 constant CFG_ILRAMEN : integer := 0;
53 constant CFG_ILRAMADDR: integer := 16#8E#;
54 constant CFG_ILRAMSZ : integer := 1;
55 constant CFG_DCEN : integer := 1;
56 constant CFG_DSETS : integer := 1;
57 constant CFG_DSETSZ : integer := 8;
58 constant CFG_DLINE : integer := 8;
59 constant CFG_DREPL : integer := 0;
60 constant CFG_DLOCK : integer := 0;
61 constant CFG_DSNOOP : integer := 0 + 0*2 + 4*0;
62 constant CFG_DFIXED : integer := 16#0#;
63 constant CFG_DLRAMEN : integer := 0;
64 constant CFG_DLRAMADDR: integer := 16#8F#;
65 constant CFG_DLRAMSZ : integer := 1;
66 constant CFG_MMUEN : integer := 0;
67 constant CFG_ITLBNUM : integer := 8;
68 constant CFG_DTLBNUM : integer := 2;
69 constant CFG_TLB_TYPE : integer := 1 + 0*2;
70 constant CFG_TLB_REP : integer := 1;
71 constant CFG_MMU_PAGE : integer := 0;
72 constant CFG_DSU : integer := 1;
73 constant CFG_ITBSZ : integer := 0 + 64*0;
74 constant CFG_ATBSZ : integer := 0;
75 constant CFG_AHBPF : integer := 0;
76 constant CFG_LEON3FT_EN : integer := 0;
77 constant CFG_IUFT_EN : integer := 0;
78 constant CFG_FPUFT_EN : integer := 0;
79 constant CFG_RF_ERRINJ : integer := 0;
80 constant CFG_CACHE_FT_EN : integer := 0;
81 constant CFG_CACHE_ERRINJ : integer := 0;
82 constant CFG_LEON3_NETLIST: integer := 0;
83 constant CFG_DISAS : integer := 0 + 0;
84 constant CFG_PCLOW : integer := 2;
85 constant CFG_STAT_ENABLE : integer := 0;
86 constant CFG_STAT_CNT : integer := 1;
87 constant CFG_STAT_NMAX : integer := 0;
88 constant CFG_STAT_DSUEN : integer := 0;
89 constant CFG_NP_ASI : integer := 0;
90 constant CFG_WRPSR : integer := 0;
91 constant CFG_ALTWIN : integer := 0;
92 constant CFG_REX : integer := 0;
93 -- AMBA settings
94 constant CFG_DEFMST : integer := (0);
95 constant CFG_RROBIN : integer := 1;
96 constant CFG_SPLIT : integer := 1;
97 constant CFG_FPNPEN : integer := 0;
98 constant CFG_AHBIO : integer := 16#FFF#;
99 constant CFG_APBADDR : integer := 16#800#;
100 constant CFG_AHB_MON : integer := 0;
101 constant CFG_AHB_MONERR : integer := 0;
102 constant CFG_AHB_MONWAR : integer := 0;
103 constant CFG_AHB_DTRACE : integer := 0;
104 -- DSU UART
105 constant CFG_AHB_UART : integer := 1;
106 -- JTAG based DSU interface
107 constant CFG_AHB_JTAG : integer := 1;
108 -- Xilinx MIG
109 constant CFG_MIG_DDR2 : integer := 1;
110 constant CFG_MIG_RANKS : integer := (1);
111 constant CFG_MIG_COLBITS : integer := (10);
112 constant CFG_MIG_ROWBITS : integer := (13);
113 constant CFG_MIG_BANKBITS: integer := (2);
114 constant CFG_MIG_HMASK : integer := 16#FC0#;
115 -- AHB ROM
116 constant CFG_AHBROMEN : integer := 1;
117 constant CFG_AHBROPIP : integer := 0;
118 constant CFG_AHBRODDR : integer := 16#000#;
119 constant CFG_ROMADDR : integer := 16#100#;
120 constant CFG_ROMMASK : integer := 16#E00# + 16#100#;
121 -- AHB RAM
122 constant CFG_AHBRAMEN : integer := 1;
123 constant CFG_AHBRSZ : integer := 4;
124 constant CFG_AHBRADDR : integer := 16#A00#;
125 constant CFG_AHBRPIPE : integer := 0;
126 -- UART 1
127 constant CFG_UART1_ENABLE : integer := 1;
128 constant CFG_UART1_FIFO : integer := 4;
129 -- LEON3 interrupt controller
130 constant CFG_IRQ3_ENABLE : integer := 1;
131 constant CFG_IRQ3_NSEC : integer := 0;
132 -- Modular timer
133 constant CFG_GPT_ENABLE : integer := 1;
134 constant CFG_GPT_NTIM : integer := (2);
135 constant CFG_GPT_SW : integer := (8);
136 constant CFG_GPT_TW : integer := (32);
137 constant CFG_GPT_IRQ : integer := (8);
138 constant CFG_GPT_SEPIRQ : integer := 1;
139 constant CFG_GPT_WDOGEN : integer := 0;
140 constant CFG_GPT_WDOG : integer := 16#0#;
141 -- GPIO port
142 constant CFG_GRGPIO_ENABLE : integer := 1;
143 constant CFG_GRGPIO_IMASK : integer := 16#0000#;
144 constant CFG_GRGPIO_WIDTH : integer := 1;
145
146 -- SPI controller
147 constant CFG_SPICTRL_ENABLE : integer := 1;
148 constant CFG_SPICTRL_NUM : integer := (1);
149 constant CFG_SPICTRL_SLVS : integer := (1);
150 constant CFG_SPICTRL_FIFO : integer := (2);
151 constant CFG_SPICTRL_SLVREG : integer := 1;
152 constant CFG_SPICTRL_ODMODE : integer := 1;
153 constant CFG_SPICTRL_AM : integer := 0;
154 constant CFG_SPICTRL_ASEL : integer := 0;
155 constant CFG_SPICTRL_TWEN : integer := 0;
156 constant CFG_SPICTRL_MAXWLEN : integer := (0);
157 constant CFG_SPICTRL_SYNCRAM : integer := 0;
158 constant CFG_SPICTRL_FT : integer := 0;
159
160 -- GRLIB debugging
161 constant CFG_DUART : integer := 0;
162 end;
@@ -0,0 +1,425
1
2
3 library ieee;
4 use ieee.std_logic_1164.all;
5 USE IEEE.NUMERIC_STD.ALL;
6 library grlib;
7 use grlib.amba.all;
8 use grlib.stdlib.all;
9 use grlib.devices.all;
10 library techmap;
11 use techmap.gencomp.all;
12 use techmap.allclkgen.all;
13 library gaisler;
14 use gaisler.memctrl.all;
15 use gaisler.leon3.all;
16 use gaisler.uart.all;
17 use gaisler.misc.all;
18 --pragma translate_off
19 use gaisler.sim.all;
20 --pragma translate_on
21 library opencores;
22 use opencores.spwpkg.all;
23 use opencores.spwambapkg.all;
24 LIBRARY lpp;
25 USE lpp.general_purpose.ALL;
26 use lpp.lpp_amba.all;
27 USE lpp.lpp_lfr_management.ALL;
28
29 use work.config.all;
30
31 library unisim;
32 use unisim.vcomponents.all;
33
34 entity leon3mp is
35 generic (
36 fabtech : integer := CFG_FABTECH;
37 memtech : integer := CFG_MEMTECH;
38 padtech : integer := CFG_PADTECH;
39 clktech : integer := CFG_CLKTECH;
40 disas : integer := CFG_DISAS; -- Enable disassembly to console
41 dbguart : integer := CFG_DUART; -- Print UART on console
42 pclow : integer := CFG_PCLOW
43 );
44 port (
45 CLK50 : in std_logic;
46 LEDS : inout std_logic_vector(7 downto 0);
47 SW : in std_logic_vector(4 downto 1);
48 dram_addr : out std_logic_vector(12 downto 0);
49 dram_ba_0 : out std_logic;
50 dram_ba_1 : out std_logic;
51 dram_dq : inout std_logic_vector(15 downto 0);
52
53 dram_clk : out std_logic;
54 dram_cke : out std_logic;
55 dram_cs_n : out std_logic;
56 dram_we_n : out std_logic; -- sdram write enable
57 dram_ras_n : out std_logic; -- sdram ras
58 dram_cas_n : out std_logic; -- sdram cas
59 dram_ldqm : out std_logic; -- sdram ldqm
60 dram_udqm : out std_logic; -- sdram udqm
61 uart_txd : out std_logic; -- DSU tx data
62 uart_rxd : in std_logic; -- DSU rx data
63
64 spw_rxdp : in std_logic;
65 spw_rxdn : in std_logic;
66 spw_rxsp : in std_logic;
67 spw_rxsn : in std_logic;
68 spw_txdp : out std_logic;
69 spw_txdn : out std_logic;
70 spw_txsp : out std_logic;
71 spw_txsn : out std_logic
72 );
73 end;
74
75 architecture rtl of leon3mp is
76 signal resetn : std_logic;
77 signal clkm, rstn, rstraw, rst : std_logic;
78 signal clk_50 : std_logic := '0';
79 signal clkm_inv : std_logic := '0';
80
81 signal cptr : std_logic_vector(29 downto 0);
82 constant BOARD_FREQ : integer := 25000; -- CLK input frequency in KHz
83 constant CPU_FREQ : integer := BOARD_FREQ * CFG_CLKMUL / CFG_CLKDIV; -- cpu frequency in KHz
84 signal sdi : sdctrl_in_type;
85 signal sdo : sdctrl_out_type;
86
87 --AMBA bus standard interface signals--
88 signal apbi : apb_slv_in_type;
89 signal apbo : apb_slv_out_vector := (others => apb_none);
90 signal ahbsi : ahb_slv_in_type;
91 signal ahbso : ahb_slv_out_vector := (others => ahbs_none);
92 signal ahbmi : ahb_mst_in_type;
93 signal ahbmo : ahb_mst_out_vector := (others => ahbm_none);
94
95 signal cgi : clkgen_in_type;
96 signal cgo : clkgen_out_type;
97
98 signal dui : uart_in_type;
99 signal duo : uart_out_type;
100
101 signal irqi : irq_in_vector(0 to CFG_NCPU-1);
102 signal irqo : irq_out_vector(0 to CFG_NCPU-1);
103
104 signal dbgi : l3_debug_in_vector(0 to CFG_NCPU-1);
105 signal dbgo : l3_debug_out_vector(0 to CFG_NCPU-1);
106
107 signal dsui : dsu_in_type;
108 signal dsuo : dsu_out_type;
109
110
111 signal gpti : gptimer_in_type;
112 signal gpto : gptimer_out_type;
113
114 signal gpioi_0 : gpio_in_type;
115 signal gpioo_0 : gpio_out_type;
116
117 signal dsubren : std_logic :='0';
118
119 signal spw_di: std_logic;
120 signal spw_si: std_logic;
121 signal spw_do: std_logic;
122 signal spw_so: std_logic;
123 signal spw_tick_in: std_logic;
124 signal spw_tick_out: std_logic;
125
126 -- AdvancedTrigger
127 SIGNAL Trigger : STD_LOGIC;
128 SIGNAL coarse_time : STD_LOGIC_VECTOR(31 DOWNTO 0);
129 SIGNAL fine_time : STD_LOGIC_VECTOR(15 DOWNTO 0);
130
131 component sdctrl16
132 generic (
133 hindex : integer := 0;
134 haddr : integer := 0;
135 hmask : integer := 16#f00#;
136 ioaddr : integer := 16#000#;
137 iomask : integer := 16#fff#;
138 wprot : integer := 0;
139 invclk : integer := 0;
140 fast : integer := 0;
141 pwron : integer := 0;
142 sdbits : integer := 16;
143 oepol : integer := 0;
144 pageburst : integer := 0;
145 mobile : integer := 0
146 );
147 port (
148 rst : in std_ulogic;
149 clk : in std_ulogic;
150 ahbsi : in ahb_slv_in_type;
151 ahbso : out ahb_slv_out_type;
152 sdi : in sdctrl_in_type;
153 sdo : out sdctrl_out_type
154 );
155 end component;
156
157 begin
158 resetn <= SW(1);
159
160 clk_pad : clkpad generic map (tech => padtech) port map (CLK50, clk_50);
161 process(clk_50)
162 begin
163 if clk_50'event and clk_50='1' then
164 clkm <= not clkm;
165 end if;
166 end process;
167 clkm_inv <= not clkm;
168
169 resetn_pad : inpad generic map (tech => padtech) port map (resetn, rst);
170 rst0 : rstgen -- reset generator (reset is active LOW)
171 port map (rst, clkm, '1', rstn, rstraw);
172
173
174 ----------------------------------------------------------------------
175 --- AHB CONTROLLER --------------------------------------------------
176 ----------------------------------------------------------------------
177
178 ahb0 : ahbctrl -- AHB arbiter/multiplexer
179 generic map (defmast => CFG_DEFMST, split => CFG_SPLIT,
180 rrobin => CFG_RROBIN, ioaddr => CFG_AHBIO,
181 nahbm => CFG_NCPU+CFG_AHB_UART+1, nahbs => 8)
182
183 port map (rstn, clkm, ahbmi, ahbmo, ahbsi, ahbso);
184
185 ----------------------------------------------------------------------
186 ----- LEON3 processor and DSU ---------------------------------------
187 ----------------------------------------------------------------------
188
189 cpu : for i in 0 to CFG_NCPU-1 generate
190 nosh : if CFG_GRFPUSH = 0 generate
191 u0 : leon3s -- LEON3 processor
192 generic map (i, fabtech, memtech, CFG_NWIN, CFG_DSU, CFG_FPU*(1-CFG_GRFPUSH), CFG_V8,
193 0, CFG_MAC, pclow, CFG_NOTAG, CFG_NWP, CFG_ICEN, CFG_IREPL, CFG_ISETS, CFG_ILINE,
194 CFG_ISETSZ, CFG_ILOCK, CFG_DCEN, CFG_DREPL, CFG_DSETS, CFG_DLINE, CFG_DSETSZ,
195 CFG_DLOCK, CFG_DSNOOP, CFG_ILRAMEN, CFG_ILRAMSZ, CFG_ILRAMADDR, CFG_DLRAMEN,
196 CFG_DLRAMSZ, CFG_DLRAMADDR, CFG_MMUEN, CFG_ITLBNUM, CFG_DTLBNUM, CFG_TLB_TYPE, CFG_TLB_REP,
197 CFG_LDDEL, disas, CFG_ITBSZ, CFG_PWD, CFG_SVT, CFG_RSTADDR, CFG_NCPU-1,
198 0, 0, CFG_MMU_PAGE, CFG_BP, CFG_NP_ASI, CFG_WRPSR)
199 port map (clkm, rstn, ahbmi, ahbmo(i), ahbsi, ahbso,
200 irqi(i), irqo(i), dbgi(i), dbgo(i));
201 end generate;
202 end generate;
203
204 --ledr[0] lit when leon 3 debugvector signals error
205 dsugen : if CFG_DSU = 1 generate
206 dsu0 : dsu3 -- LEON3 Debug Support Unit (slave)
207 generic map (hindex => 2, haddr => 16#900#, hmask => 16#F00#,
208 ncpu => CFG_NCPU, tbits => 30, tech => memtech, irq => 0, kbytes => CFG_ATBSZ)
209 port map (rstn, clkm, ahbmi, ahbsi, ahbso(2), dbgo, dbgi, dsui, dsuo);
210 dsui.enable <= '1';
211
212 end generate;
213 nodsu : if CFG_DSU = 0 generate
214 ahbso(2) <= ahbs_none; dsuo.tstop <= '0'; dsuo.active <= '0'; --no timer freeze, no light.
215 end generate;
216
217 dcomgen : if CFG_AHB_UART = 1 generate
218 dcom0: ahbuart -- Debug UART
219 generic map (hindex => CFG_NCPU, pindex => 7, paddr => 7)
220 port map (rstn, clkm, dui, duo, apbi, apbo(7), ahbmi, ahbmo(CFG_NCPU));
221 end generate;
222 uart_txd <= duo.txd;
223 dui.rxd <= uart_rxd;
224
225
226 ----------------------------------------------------------------------
227 --- Memory controllers ----------------------------------------------
228 ----------------------------------------------------------------------
229
230
231 sdc : sdctrl16 generic map (hindex => 3, haddr => 16#400#, hmask => 16#FE0#, -- hmask => 16#C00#,
232 ioaddr => 1, fast => 0, pwron => 0, invclk => 0,
233 sdbits => 16, pageburst => 2)
234 port map (rstn, clkm, ahbsi, ahbso(3), sdi, sdo);
235 sa_pad : outpadv generic map (width => 13, tech => padtech)
236 port map (dram_addr, sdo.address(14 downto 2));
237 ba0_pad : outpad generic map (tech => padtech)
238 port map (dram_ba_0, sdo.address(15));
239 ba1_pad : outpad generic map (tech => padtech)
240 port map (dram_ba_1, sdo.address(16));
241 sd_pad : iopadvv generic map (width => 16, tech => padtech)
242 port map (dram_dq(15 downto 0), sdo.data(15 downto 0), sdo.vbdrive(15 downto 0), sdi.data(15 downto 0));
243 sdcke_pad : outpad generic map (tech => padtech)
244 port map (dram_cke, sdo.sdcke(0));
245 sdwen_pad : outpad generic map (tech => padtech)
246 port map (dram_we_n, sdo.sdwen);
247 sdcsn_pad : outpad generic map (tech => padtech)
248 port map (dram_cs_n, sdo.sdcsn(0));
249 sdras_pad : outpad generic map (tech => padtech)
250 port map (dram_ras_n, sdo.rasn);
251 sdcas_pad : outpad generic map (tech => padtech)
252 port map (dram_cas_n, sdo.casn);
253 sdldqm_pad : outpad generic map (tech => padtech)
254 port map (dram_ldqm, sdo.dqm(0) );
255 sdudqm_pad : outpad generic map (tech => padtech)
256 port map (dram_udqm, sdo.dqm(1));
257 dram_clk_pad : outpad generic map (tech => padtech)
258 port map (dram_clk, clkm_inv);
259
260 ----------------------------------------------------------------------
261 --- APB Bridge and various periherals -------------------------------
262 ----------------------------------------------------------------------
263
264 apb0 : apbctrl -- AHB/APB bridge
265 generic map (hindex => 1, haddr => CFG_APBADDR)
266 port map (rstn, clkm, ahbsi, ahbso(1), apbi, apbo );
267
268 ----------------------------------------------------------------------------------------
269
270 irqctrl : if CFG_IRQ3_ENABLE /= 0 generate
271 irqctrl0 : irqmp -- interrupt controller
272 generic map (pindex => 2, paddr => 2, ncpu => CFG_NCPU)
273 port map (rstn, clkm, apbi, apbo(2), irqo, irqi);
274 end generate;
275 irq3 : if CFG_IRQ3_ENABLE = 0 generate
276 x : for i in 0 to CFG_NCPU-1 generate irqi(i).irl <= "0000"; end generate;
277 apbo(2) <= apb_none;
278 end generate;
279
280 --Timer unit, generates interrupts when a timer underflow.
281 gpt : if CFG_GPT_ENABLE /= 0 generate
282 timer0 : gptimer -- timer unit
283 generic map (pindex => 3, paddr => 3, pirq => CFG_GPT_IRQ,
284 sepirq => CFG_GPT_SEPIRQ, sbits => CFG_GPT_SW, ntimers => CFG_GPT_NTIM,
285 nbits => CFG_GPT_TW)
286 port map (rstn, clkm, apbi, apbo(3), gpti, gpto);
287 gpti <= gpti_dhalt_drive(dsuo.tstop);
288 end generate;
289 notim : if CFG_GPT_ENABLE = 0 generate apbo(3) <= apb_none; end generate;
290
291 gpio0 : if CFG_GRGPIO_ENABLE /= 0 generate -- GR GPIO0 unit
292 grgpio0: grgpio
293 generic map( pindex => 9, paddr => 9, imask => CFG_GRGPIO_IMASK, nbits => 4)
294 port map( rstn, clkm, apbi, apbo(9), gpioi_0, gpioo_0);
295 pio_pads : for i in 0 to 3 generate
296 pio_pad : iopad generic map (tech => padtech)
297 port map (LEDS(i), gpioo_0.dout(i), gpioo_0.oen(i), gpioi_0.din(i));
298 end generate;
299 end generate;
300 nogpio0: if CFG_GRGPIO_ENABLE = 0 generate apbo(9) <= apb_none; end generate;
301
302
303 -------------------------------------------------------------------------------
304 -- APB_LFR_MANAGEMENT ---------------------------------------------------------
305 -------------------------------------------------------------------------------
306 apb_lfr_management_1 : apb_lfr_management
307 GENERIC MAP (
308 tech => fabtech,
309 pindex => 6,
310 paddr => 6,
311 pmask => 16#fff#,
312 NB_SECOND_DESYNC => 60) -- 60 secondes of desynchronization before CoarseTime's MSB is Set
313 PORT MAP (
314 clk25MHz => clkm,
315 resetn_25MHz => rstn,
316 grspw_tick => spw_tick_out,
317 apbi => apbi,
318 apbo => apbo(6),
319 HK_sample => X"0000",
320 HK_val => '0',
321 HK_sel => OPEN,
322 DAC_SDO => OPEN,
323 DAC_SCK => OPEN,
324 DAC_SYNC => OPEN,
325 DAC_CAL_EN => OPEN,
326 coarse_time => coarse_time,
327 fine_time => fine_time,
328 LFR_soft_rstn => OPEN
329 );
330
331 ----------------------------------------------------------------------
332 --- APB_ADVANCED_TRIGGER -----------------------------------------------------------
333 ----------------------------------------------------------------------
334 advtrig0: APB_ADVANCED_TRIGGER
335 generic map(
336 pindex => 5,
337 paddr => 5)
338 port map(
339 rstn => rstn,
340 clk => clkm,
341 apbi => apbi,
342 apbo => apbo(5),
343
344 SPW_Tickout => spw_tick_out,
345 CoarseTime => coarse_time,
346 FineTime => fine_time,
347
348 Trigger => Trigger
349 );
350
351
352 DISCO1_TRIG1_PAD : outpad GENERIC MAP (tech => inferred)
353 PORT MAP (LEDS(4), Trigger);
354 DISCO2_TRIG1_PAD : outpad GENERIC MAP (tech => inferred)
355 PORT MAP (LEDS(5), Trigger);
356 DISCO3_TRIG1_PAD : outpad GENERIC MAP (tech => inferred)
357 PORT MAP (LEDS(6), Trigger);
358 DISCO4_TRIG1_PAD : outpad GENERIC MAP (tech => inferred)
359 PORT MAP (LEDS(7), Trigger);
360
361 -----------------------------------------------------------------------
362 --- SpaceWire Light --------------------------------------------------
363 -----------------------------------------------------------------------
364
365 spw0: spwamba
366 generic map (
367 tech => memtech,
368 hindex => 2,
369 pindex => 10,
370 paddr => 10,
371 pirq => 10,
372 sysfreq => 25.0e6,
373 txclkfreq => 50.0e6,
374 rximpl => impl_fast,
375 rxchunk => 1,
376 tximpl => impl_fast,
377 timecodegen => true,
378 rxfifosize => 11,
379 txfifosize => 11,
380 desctablesize => 10,
381 maxburst => 3 )
382 port map (
383 clk => clkm,
384 rxclk => clk_50,
385 txclk => clk_50,
386 rstn => rstn,
387 apbi => apbi,
388 apbo => apbo(10),
389 ahbi => ahbmi,
390 ahbo => ahbmo(2),
391 tick_in => spw_tick_in,
392 tick_out => spw_tick_out,
393 spw_di => spw_di,
394 spw_si => spw_si,
395 spw_do => spw_do,
396 spw_so => spw_so );
397
398 spw_tick_in <= gpto.tick(2) when CFG_GPT_ENABLE /= 0 else '0';
399
400 spw_rxd_pad: inpad_ds
401 generic map (padtech, lvds, x33v)
402 port map (spw_rxdp, spw_rxdn, spw_di);
403 spw_rxs_pad: inpad_ds
404 generic map (padtech, lvds, x33v)
405 port map (spw_rxsp, spw_rxsn, spw_si);
406 -- spw_txd_pad: outpad_ds
407 -- generic map (padtech, lvds, x33v)
408 -- port map (spw_txdp, spw_txdn, spw_do, '0');
409 -- spw_txs_pad: outpad_ds
410 -- generic map (padtech, lvds, x33v)
411 -- port map (spw_txsp, spw_txsn, spw_so, '0');
412
413
414 spw_txdp_pad : outpad generic map (tech => padtech)
415 port map (spw_txdp, spw_do);
416 spw_txdn_pad : outpad generic map (tech => padtech)
417 port map (spw_txdn, not spw_do);
418
419 spw_txsp_pad : outpad generic map (tech => padtech)
420 port map (spw_txsp, spw_so);
421 spw_txsn_pad : outpad generic map (tech => padtech)
422 port map (spw_txsn, not spw_so);
423
424 end rtl;
425
@@ -0,0 +1,4
1
2 NET CLK50 PERIOD = 20.0 ;
3
4
This diff has been collapsed as it changes many lines, (1550 lines changed) Show them Hide them
@@ -0,0 +1,1550
1
2 --*****************************************************************************
3 --
4 -- Micron Semiconductor Products, Inc.
5 --
6 -- Copyright 1997, Micron Semiconductor Products, Inc.
7 -- All rights reserved.
8 --
9 --*****************************************************************************
10
11 -- pragma translate_off
12
13 library ieee;
14 use ieee.std_logic_1164.ALL;
15 use std.textio.all;
16
17 PACKAGE mti_pkg IS
18
19 FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC;
20 FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER;
21 FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER;
22 FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER;
23 PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR);
24
25
26 END mti_pkg;
27
28 PACKAGE BODY mti_pkg IS
29
30 -- Convert BIT to STD_LOGIC
31 FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC IS
32 BEGIN
33 CASE s IS
34 WHEN '0' => RETURN ('0');
35 WHEN '1' => RETURN ('1');
36 WHEN OTHERS => RETURN ('0');
37 END CASE;
38 END;
39
40 -- Convert STD_LOGIC to INTEGER
41 FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS
42 VARIABLE result : INTEGER := 0;
43 VARIABLE weight : INTEGER := 1;
44 BEGIN
45 IF input = '1' THEN
46 result := weight;
47 ELSE
48 result := 0; -- if unknowns, default to logic 0
49 END IF;
50 RETURN result;
51 END TO_INTEGER;
52
53 -- Convert BIT_VECTOR to INTEGER
54 FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS
55 VARIABLE result : INTEGER := 0;
56 VARIABLE weight : INTEGER := 1;
57 BEGIN
58 FOR i IN input'LOW TO input'HIGH LOOP
59 IF input(i) = '1' THEN
60 result := result + weight;
61 ELSE
62 result := result + 0; -- if unknowns, default to logic 0
63 END IF;
64 weight := weight * 2;
65 END LOOP;
66 RETURN result;
67 END TO_INTEGER;
68
69 -- Convert STD_LOGIC_VECTOR to INTEGER
70 FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS
71 VARIABLE result : INTEGER := 0;
72 VARIABLE weight : INTEGER := 1;
73 BEGIN
74 FOR i IN input'LOW TO input'HIGH LOOP
75 IF input(i) = '1' THEN
76 result := result + weight;
77 ELSE
78 result := result + 0; -- if unknowns, default to logic 0
79 END IF;
80 weight := weight * 2;
81 END LOOP;
82 RETURN result;
83 END TO_INTEGER;
84
85 -- Conver INTEGER to BIT_VECTOR
86 PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS
87 VARIABLE work,offset,outputlen,j : INTEGER := 0;
88 BEGIN
89 --length of vector
90 IF output'LENGTH > 32 THEN --'
91 outputlen := 32;
92 offset := output'LENGTH - 32; --'
93 IF input >= 0 THEN
94 FOR i IN offset-1 DOWNTO 0 LOOP
95 output(output'HIGH - i) := '0'; --'
96 END LOOP;
97 ELSE
98 FOR i IN offset-1 DOWNTO 0 LOOP
99 output(output'HIGH - i) := '1'; --'
100 END LOOP;
101 END IF;
102 ELSE
103 outputlen := output'LENGTH; --'
104 END IF;
105 --positive value
106 IF (input >= 0) THEN
107 work := input;
108 j := outputlen - 1;
109 FOR i IN 1 to 32 LOOP
110 IF j >= 0 then
111 IF (work MOD 2) = 0 THEN
112 output(output'HIGH-j-offset) := '0'; --'
113 ELSE
114 output(output'HIGH-j-offset) := '1'; --'
115 END IF;
116 END IF;
117 work := work / 2;
118 j := j - 1;
119 END LOOP;
120 IF outputlen = 32 THEN
121 output(output'HIGH) := '0'; --'
122 END IF;
123 --negative value
124 ELSE
125 work := (-input) - 1;
126 j := outputlen - 1;
127 FOR i IN 1 TO 32 LOOP
128 IF j>= 0 THEN
129 IF (work MOD 2) = 0 THEN
130 output(output'HIGH-j-offset) := '1'; --'
131 ELSE
132 output(output'HIGH-j-offset) := '0'; --'
133 END IF;
134 END IF;
135 work := work / 2;
136 j := j - 1;
137 END LOOP;
138 IF outputlen = 32 THEN
139 output(output'HIGH) := '1'; --'
140 END IF;
141 END IF;
142 END TO_BITVECTOR;
143
144 END mti_pkg;
145
146 -----------------------------------------------------------------------------------------
147 --
148 -- File Name: MT48LC16M16A2.VHD
149 -- Version: 0.0g
150 -- Date: June 29th, 2000
151 -- Model: Behavioral
152 -- Simulator: Model Technology (PC version 5.3 PE)
153 --
154 -- Dependencies: None
155 --
156 -- Author: Son P. Huynh
157 -- Email: sphuynh@micron.com
158 -- Phone: (208) 368-3825
159 -- Company: Micron Technology, Inc.
160 -- Part Number: MT48LC16M16A2 (4Mb x 16 x 4 Banks)
161 --
162 -- Description: Micron 256Mb SDRAM
163 --
164 -- Limitation: - Doesn't check for 4096-cycle refresh --'
165 --
166 -- Note: - Set simulator resolution to "ps" accuracy
167 --
168 -- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
169 -- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
170 -- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
171 -- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
172 --
173 -- Copyright (c) 1998 Micron Semiconductor Products, Inc.
174 -- All rights researved
175 --
176 -- Rev Author Phone Date Changes
177 -- ---- ---------------------------- ---------- -------------------------------------
178 -- 0.0g Son Huynh 208-368-3825 06/29/2000 Add Load/Dump memory array
179 -- Micron Technology Inc. Modify tWR + tRAS timing check
180 --
181 -- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto)
182 -- Micron Technology Inc. Fix tWR = 15 ns (Manual)
183 -- Fix tRP (Autoprecharge to AutoRefresh)
184 --
185 -- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP
186 -- Micron Technology Inc. Fix tRC check in Load Mode Register
187 --
188 -- 0.0b Son P. Huynh 208-368-3825 01/06/1998 Derive from 64Mb SDRAM model
189 -- Micron Technology Inc.
190 --
191 -----------------------------------------------------------------------------------------
192
193 LIBRARY STD;
194 USE STD.TEXTIO.ALL;
195 LIBRARY IEEE;
196 USE IEEE.STD_LOGIC_1164.ALL;
197 LIBRARY WORK;
198 USE WORK.MTI_PKG.ALL;
199 use std.textio.all;
200
201 library grlib;
202 use grlib.stdlib.all;
203 use grlib.stdio.all;
204
205 ENTITY mt48lc16m16a2 IS
206 GENERIC (
207 -- Timing Parameters for -75 (PC133) and CAS Latency = 2
208 tAC : TIME := 6.0 ns;
209 tHZ : TIME := 7.0 ns;
210 tOH : TIME := 2.7 ns;
211 tMRD : INTEGER := 2; -- 2 Clk Cycles
212 tRAS : TIME := 44.0 ns;
213 tRC : TIME := 66.0 ns;
214 tRCD : TIME := 20.0 ns;
215 tRP : TIME := 20.0 ns;
216 tRRD : TIME := 15.0 ns;
217 tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
218 tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns)
219
220 tAH : TIME := 0.8 ns;
221 tAS : TIME := 1.5 ns;
222 tCH : TIME := 2.5 ns;
223 tCL : TIME := 2.5 ns;
224 tCK : TIME := 10.0 ns;
225 tDH : TIME := 0.8 ns;
226 tDS : TIME := 1.5 ns;
227 tCKH : TIME := 0.8 ns;
228 tCKS : TIME := 1.5 ns;
229 tCMH : TIME := 0.8 ns;
230 tCMS : TIME := 1.5 ns;
231
232 addr_bits : INTEGER := 13;
233 data_bits : INTEGER := 16;
234 col_bits : INTEGER := 9;
235 index : INTEGER := 0;
236 fname : string := "ram.srec" -- File to read from
237 );
238 PORT (
239 Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
240 Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
241 Ba : IN STD_LOGIC_VECTOR := "00";
242 Clk : IN STD_LOGIC := '0';
243 Cke : IN STD_LOGIC := '1';
244 Cs_n : IN STD_LOGIC := '1';
245 Ras_n : IN STD_LOGIC := '1';
246 Cas_n : IN STD_LOGIC := '1';
247 We_n : IN STD_LOGIC := '1';
248 Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"
249 );
250 END mt48lc16m16a2;
251
252 ARCHITECTURE behave OF mt48lc16m16a2 IS
253 TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, LOAD_FILE, DUMP_FILE);
254 TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER;
255 TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME;
256 TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT;
257 TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0);
258 TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0);
259 TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State;
260 SIGNAL Operation : State := NOP;
261 SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
262 SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0';
263 SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0';
264 SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0';
265 SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0';
266 SIGNAL Ras_in, Cas_in, We_in : BIT := '0';
267 SIGNAL Write_burst_mode : BIT := '0';
268 SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0';
269
270 -- Checking internal wires
271 SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000";
272 SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000";
273 SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0';
274 SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00";
275 SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
276 SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
277
278 BEGIN
279 -- CS# Decode
280 WITH Cs_n SELECT
281 Cas_in <= TO_BIT (Cas_n, '1') WHEN '0',
282 '1' WHEN '1',
283 '1' WHEN OTHERS;
284 WITH Cs_n SELECT
285 Ras_in <= TO_BIT (Ras_n, '1') WHEN '0',
286 '1' WHEN '1',
287 '1' WHEN OTHERS;
288 WITH Cs_n SELECT
289 We_in <= TO_BIT (We_n, '1') WHEN '0',
290 '1' WHEN '1',
291 '1' WHEN OTHERS;
292
293 -- Commands Decode
294 Active_enable <= NOT(Ras_in) AND Cas_in AND We_in;
295 Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in;
296 Burst_term <= Ras_in AND Cas_in AND NOT(We_in);
297 Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in);
298 Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in);
299 Read_enable <= Ras_in AND NOT(Cas_in) AND We_in;
300 Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in);
301
302 -- Burst Length Decode
303 Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0));
304 Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0);
305 Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0));
306 Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
307
308 -- CAS Latency Decode
309 Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4));
310 Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4);
311
312 -- Write Burst Mode
313 Write_burst_mode <= Mode_reg(9);
314
315 -- RAS Clock for checking tWR and tRP
316 PROCESS
317 variable Clk0, Clk1 : integer := 0;
318 begin
319 RAS_clk <= '1';
320 wait for 0.5 ns;
321 RAS_clk <= '0';
322 wait for 0.5 ns;
323 if Clk0 > 100 or Clk1 > 100 then
324 wait;
325 else
326 if Clk = '1' and Cke = '1' then
327 Clk0 := 0;
328 Clk1 := Clk1 + 1;
329 elsif Clk = '0' and Cke = '1' then
330 Clk0 := Clk0 + 1;
331 Clk1 := 0;
332 end if;
333 end if;
334 END PROCESS;
335
336 -- System Clock
337 int_clk : PROCESS (Clk)
338 begin
339 IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN --'
340 CkeZ <= TO_BIT(Cke, '1');
341 END IF;
342 Sys_clk <= CkeZ AND TO_BIT(Clk, '0');
343 END PROCESS;
344
345 state_register : PROCESS
346 -- NOTE: The extra bits in RAM_TYPE is for checking memory access. A logic 1 means
347 -- the location is in use. This will be checked when doing memory DUMP.
348 TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits DOWNTO 0);
349 TYPE ram_pntr IS ACCESS ram_type;
350 TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr;
351 VARIABLE Bank0 : ram_stor;
352 VARIABLE Bank1 : ram_stor;
353 VARIABLE Bank2 : ram_stor;
354 VARIABLE Bank3 : ram_stor;
355 VARIABLE Row_index, Col_index : INTEGER := 0;
356 VARIABLE Dq_temp : BIT_VECTOR (data_bits DOWNTO 0) := (OTHERS => '0');
357
358 VARIABLE Col_addr : Array4xCBV;
359 VARIABLE Bank_addr : Array4x2BV;
360 VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00";
361
362 VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00";
363 VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
364 VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
365 VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
366 VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
367 VARIABLE Burst_counter : INTEGER := 0;
368
369 VARIABLE Command : Array_state;
370 VARIABLE Bank_precharge : Array4x2BV;
371 VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0');
372 VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0');
373 VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0');
374 VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0');
375 VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0');
376 VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0');
377 VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00";
378 VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
379 VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0);
380
381 VARIABLE Data_in_enable, Data_out_enable : BIT := '0';
382 VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0';
383 VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0';
384
385 -- Timing Check
386 VARIABLE MRD_chk : INTEGER := 0;
387 VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0);
388 VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
389 VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns);
390 VARIABLE RC_chk, RRD_chk : TIME := 0 ns;
391 VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns;
392 VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns;
393 VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns;
394
395 -- Load and Dumb variables
396 FILE file_load : TEXT open read_mode is fname; -- Data load
397 FILE file_dump : TEXT open write_mode is "dumpdata.txt"; -- Data dump
398 VARIABLE bank_load : bit_vector ( 1 DOWNTO 0);
399 VARIABLE rows_load : BIT_VECTOR (12 DOWNTO 0);
400 VARIABLE cols_load : BIT_VECTOR ( 8 DOWNTO 0);
401 VARIABLE data_load : BIT_VECTOR (15 DOWNTO 0);
402 VARIABLE i, j : INTEGER;
403 VARIABLE good_load : BOOLEAN;
404 VARIABLE l : LINE;
405 variable load : std_logic := '1';
406 variable dump : std_logic := '0';
407 variable ch : character;
408 variable rectype : bit_vector(3 downto 0);
409 variable recaddr : bit_vector(31 downto 0);
410 variable reclen : bit_vector(7 downto 0);
411 variable recdata : bit_vector(0 to 16*8-1);
412
413 -- Initialize empty rows
414 PROCEDURE Init_mem (Bank : bit_vector (1 DOWNTO 0); Row_index : INTEGER) IS
415 VARIABLE i, j : INTEGER := 0;
416 BEGIN
417 IF Bank = "00" THEN
418 IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty
419 Bank0 (Row_index) := NEW ram_type; -- Open new row for access
420 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros
421 FOR j IN (data_bits) DOWNTO 0 LOOP
422 Bank0 (Row_index) (i) (j) := '0';
423 END LOOP;
424 END LOOP;
425 END IF;
426 ELSIF Bank = "01" THEN
427 IF Bank1 (Row_index) = NULL THEN
428 Bank1 (Row_index) := NEW ram_type;
429 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
430 FOR j IN (data_bits) DOWNTO 0 LOOP
431 Bank1 (Row_index) (i) (j) := '0';
432 END LOOP;
433 END LOOP;
434 END IF;
435 ELSIF Bank = "10" THEN
436 IF Bank2 (Row_index) = NULL THEN
437 Bank2 (Row_index) := NEW ram_type;
438 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
439 FOR j IN (data_bits) DOWNTO 0 LOOP
440 Bank2 (Row_index) (i) (j) := '0';
441 END LOOP;
442 END LOOP;
443 END IF;
444 ELSIF Bank = "11" THEN
445 IF Bank3 (Row_index) = NULL THEN
446 Bank3 (Row_index) := NEW ram_type;
447 FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP
448 FOR j IN (data_bits) DOWNTO 0 LOOP
449 Bank3 (Row_index) (i) (j) := '0';
450 END LOOP;
451 END LOOP;
452 END IF;
453 END IF;
454 END;
455
456 -- Burst Counter
457 PROCEDURE Burst_decode IS
458 VARIABLE Col_int : INTEGER := 0;
459 VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0');
460 BEGIN
461 -- Advance Burst Counter
462 Burst_counter := Burst_counter + 1;
463
464 -- Burst Type
465 IF Mode_reg (3) = '0' THEN
466 Col_int := TO_INTEGER(Col);
467 Col_int := Col_int + 1;
468 TO_BITVECTOR (Col_int, Col_temp);
469 ELSIF Mode_reg (3) = '1' THEN
470 TO_BITVECTOR (Burst_counter, Col_vec);
471 Col_temp (2) := Col_vec (2) XOR Col_brst (2);
472 Col_temp (1) := Col_vec (1) XOR Col_brst (1);
473 Col_temp (0) := Col_vec (0) XOR Col_brst (0);
474 END IF;
475
476 -- Burst Length
477 IF Burst_length_2 = '1' THEN
478 Col (0) := Col_temp (0);
479 ELSIF Burst_length_4 = '1' THEN
480 Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0);
481 ELSIF Burst_length_8 = '1' THEN
482 Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0);
483 ELSE
484 Col := Col_temp;
485 END IF;
486
487 -- Burst Read Single Write
488 IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN
489 Data_in_enable := '0';
490 END IF;
491
492 -- Data counter
493 IF Burst_length_1 = '1' THEN
494 IF Burst_counter >= 1 THEN
495 IF Data_in_enable = '1' THEN
496 Data_in_enable := '0';
497 ELSIF Data_out_enable = '1' THEN
498 Data_out_enable := '0';
499 END IF;
500 END IF;
501 ELSIF Burst_length_2 = '1' THEN
502 IF Burst_counter >= 2 THEN
503 IF Data_in_enable = '1' THEN
504 Data_in_enable := '0';
505 ELSIF Data_out_enable = '1' THEN
506 Data_out_enable := '0';
507 END IF;
508 END IF;
509 ELSIF Burst_length_4 = '1' THEN
510 IF Burst_counter >= 4 THEN
511 IF Data_in_enable = '1' THEN
512 Data_in_enable := '0';
513 ELSIF Data_out_enable = '1' THEN
514 Data_out_enable := '0';
515 END IF;
516 END IF;
517 ELSIF Burst_length_8 = '1' THEN
518 IF Burst_counter >= 8 THEN
519 IF Data_in_enable = '1' THEN
520 Data_in_enable := '0';
521 ELSIF Data_out_enable = '1' THEN
522 Data_out_enable := '0';
523 END IF;
524 END IF;
525 END IF;
526 END;
527
528 BEGIN
529 WAIT ON Sys_clk, RAS_clk;
530 IF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '0' THEN --'
531 -- Internal Command Pipeline
532 Command(0) := Command(1);
533 Command(1) := Command(2);
534 Command(2) := Command(3);
535 Command(3) := NOP;
536
537 Col_addr(0) := Col_addr(1);
538 Col_addr(1) := Col_addr(2);
539 Col_addr(2) := Col_addr(3);
540 Col_addr(3) := (OTHERS => '0');
541
542 Bank_addr(0) := Bank_addr(1);
543 Bank_addr(1) := Bank_addr(2);
544 Bank_addr(2) := Bank_addr(3);
545 Bank_addr(3) := "00";
546
547 Bank_precharge(0) := Bank_precharge(1);
548 Bank_precharge(1) := Bank_precharge(2);
549 Bank_precharge(2) := Bank_precharge(3);
550 Bank_precharge(3) := "00";
551
552 A10_precharge(0) := A10_precharge(1);
553 A10_precharge(1) := A10_precharge(2);
554 A10_precharge(2) := A10_precharge(3);
555 A10_precharge(3) := '0';
556
557 -- Operation Decode (Optional for showing current command on posedge clock / debug feature)
558 IF Active_enable = '1' THEN
559 Operation <= ACT;
560 ELSIF Aref_enable = '1' THEN
561 Operation <= A_REF;
562 ELSIF Burst_term = '1' THEN
563 Operation <= BST;
564 ELSIF Mode_reg_enable = '1' THEN
565 Operation <= LMR;
566 ELSIF Prech_enable = '1' THEN
567 Operation <= PRECH;
568 ELSIF Read_enable = '1' THEN
569 IF Addr(10) = '0' THEN
570 Operation <= READ;
571 ELSE
572 Operation <= READ_A;
573 END IF;
574 ELSIF Write_enable = '1' THEN
575 IF Addr(10) = '0' THEN
576 Operation <= WRITE;
577 ELSE
578 Operation <= WRITE_A;
579 END IF;
580 ELSE
581 Operation <= NOP;
582 END IF;
583
584 -- Dqm pipeline for Read
585 Dqm_reg0 := Dqm_reg1;
586 Dqm_reg1 := TO_BITVECTOR(Dqm);
587
588 -- Read or Write with Auto Precharge Counter
589 IF Auto_precharge (0) = '1' THEN
590 Count_precharge (0) := Count_precharge (0) + 1;
591 END IF;
592 IF Auto_precharge (1) = '1' THEN
593 Count_precharge (1) := Count_precharge (1) + 1;
594 END IF;
595 IF Auto_precharge (2) = '1' THEN
596 Count_precharge (2) := Count_precharge (2) + 1;
597 END IF;
598 IF Auto_precharge (3) = '1' THEN
599 Count_precharge (3) := Count_precharge (3) + 1;
600 END IF;
601
602 -- Auto Precharge Timer for tWR
603 if (Burst_length_1 = '1' OR Write_burst_mode = '1') then
604 if (Count_precharge(0) = 1) then
605 Count_time(0) := NOW;
606 end if;
607 if (Count_precharge(1) = 1) then
608 Count_time(1) := NOW;
609 end if;
610 if (Count_precharge(2) = 1) then
611 Count_time(2) := NOW;
612 end if;
613 if (Count_precharge(3) = 1) then
614 Count_time(3) := NOW;
615 end if;
616 elsif (Burst_length_2 = '1') then
617 if (Count_precharge(0) = 2) then
618 Count_time(0) := NOW;
619 end if;
620 if (Count_precharge(1) = 2) then
621 Count_time(1) := NOW;
622 end if;
623 if (Count_precharge(2) = 2) then
624 Count_time(2) := NOW;
625 end if;
626 if (Count_precharge(3) = 2) then
627 Count_time(3) := NOW;
628 end if;
629 elsif (Burst_length_4 = '1') then
630 if (Count_precharge(0) = 4) then
631 Count_time(0) := NOW;
632 end if;
633 if (Count_precharge(1) = 4) then
634 Count_time(1) := NOW;
635 end if;
636 if (Count_precharge(2) = 4) then
637 Count_time(2) := NOW;
638 end if;
639 if (Count_precharge(3) = 4) then
640 Count_time(3) := NOW;
641 end if;
642 elsif (Burst_length_8 = '1') then
643 if (Count_precharge(0) = 8) then
644 Count_time(0) := NOW;
645 end if;
646 if (Count_precharge(1) = 8) then
647 Count_time(1) := NOW;
648 end if;
649 if (Count_precharge(2) = 8) then
650 Count_time(2) := NOW;
651 end if;
652 if (Count_precharge(3) = 8) then
653 Count_time(3) := NOW;
654 end if;
655 end if;
656
657 -- tMRD Counter
658 MRD_chk := MRD_chk + 1;
659
660 -- tWR Counter
661 WR_counter(0) := WR_counter(0) + 1;
662 WR_counter(1) := WR_counter(1) + 1;
663 WR_counter(2) := WR_counter(2) + 1;
664 WR_counter(3) := WR_counter(3) + 1;
665
666
667 -- Auto Refresh
668 IF Aref_enable = '1' THEN
669 -- Auto Refresh to Auto Refresh
670 ASSERT (NOW - RC_chk >= tRC)
671 REPORT "tRC violation during Auto Refresh"
672 SEVERITY WARNING;
673 -- Precharge to Auto Refresh
674 ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP)
675 REPORT "tRP violation during Auto Refresh"
676 SEVERITY WARNING;
677 -- All banks must be idle before refresh
678 IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN
679 ASSERT (FALSE)
680 REPORT "All banks must be Precharge before Auto Refresh"
681 SEVERITY WARNING;
682 END IF;
683 -- Record current tRC time
684 RC_chk := NOW;
685 END IF;
686
687 -- Load Mode Register
688 IF Mode_reg_enable = '1' THEN
689 Mode_reg <= TO_BITVECTOR (Addr);
690 IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN
691 ASSERT (FALSE)
692 REPORT "All bank must be Precharge before Load Mode Register"
693 SEVERITY WARNING;
694 END IF;
695 -- REF to LMR
696 ASSERT (NOW - RC_chk >= tRC)
697 REPORT "tRC violation during Load Mode Register"
698 SEVERITY WARNING;
699 -- LMR to LMR
700 ASSERT (MRD_chk >= tMRD)
701 REPORT "tMRD violation during Load Mode Register"
702 SEVERITY WARNING;
703 -- Record current tMRD time
704 MRD_chk := 0;
705 END IF;
706
707 -- Active Block (latch Bank and Row Address)
708 IF Active_enable = '1' THEN
709 IF Ba = "00" AND Pc_b0 = '1' THEN
710 Act_b0 := '1';
711 Pc_b0 := '0';
712 B0_row_addr := TO_BITVECTOR (Addr);
713 RCD_chk0 := NOW;
714 RAS_chk0 := NOW;
715 -- Precharge to Active Bank 0
716 ASSERT (NOW - RP_chk0 >= tRP)
717 REPORT "tRP violation during Activate Bank 0"
718 SEVERITY WARNING;
719 ELSIF Ba = "01" AND Pc_b1 = '1' THEN
720 Act_b1 := '1';
721 Pc_b1 := '0';
722 B1_row_addr := TO_BITVECTOR (Addr);
723 RCD_chk1 := NOW;
724 RAS_chk1 := NOW;
725 -- Precharge to Active Bank 1
726 ASSERT (NOW - RP_chk1 >= tRP)
727 REPORT "tRP violation during Activate Bank 1"
728 SEVERITY WARNING;
729 ELSIF Ba = "10" AND Pc_b2 = '1' THEN
730 Act_b2 := '1';
731 Pc_b2 := '0';
732 B2_row_addr := TO_BITVECTOR (Addr);
733 RCD_chk2 := NOW;
734 RAS_chk2 := NOW;
735 -- Precharge to Active Bank 2
736 ASSERT (NOW - RP_chk2 >= tRP)
737 REPORT "tRP violation during Activate Bank 2"
738 SEVERITY WARNING;
739 ELSIF Ba = "11" AND Pc_b3 = '1' THEN
740 Act_b3 := '1';
741 Pc_b3 := '0';
742 B3_row_addr := TO_BITVECTOR (Addr);
743 RCD_chk3 := NOW;
744 RAS_chk3 := NOW;
745 -- Precharge to Active Bank 3
746 ASSERT (NOW - RP_chk3 >= tRP)
747 REPORT "tRP violation during Activate Bank 3"
748 SEVERITY WARNING;
749 ELSIF Ba = "00" AND Pc_b0 = '0' THEN
750 ASSERT (FALSE)
751 REPORT "Bank 0 is not Precharged"
752 SEVERITY WARNING;
753 ELSIF Ba = "01" AND Pc_b1 = '0' THEN
754 ASSERT (FALSE)
755 REPORT "Bank 1 is not Precharged"
756 SEVERITY WARNING;
757 ELSIF Ba = "10" AND Pc_b2 = '0' THEN
758 ASSERT (FALSE)
759 REPORT "Bank 2 is not Precharged"
760 SEVERITY WARNING;
761 ELSIF Ba = "11" AND Pc_b3 = '0' THEN
762 ASSERT (FALSE)
763 REPORT "Bank 3 is not Precharged"
764 SEVERITY WARNING;
765 END IF;
766 -- Active Bank A to Active Bank B
767 IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN
768 ASSERT (FALSE)
769 REPORT "tRRD violation during Activate"
770 SEVERITY WARNING;
771 END IF;
772 -- LMR to ACT
773 ASSERT (MRD_chk >= tMRD)
774 REPORT "tMRD violation during Activate"
775 SEVERITY WARNING;
776 -- AutoRefresh to Activate
777 ASSERT (NOW - RC_chk >= tRC)
778 REPORT "tRC violation during Activate"
779 SEVERITY WARNING;
780 -- Record variable for checking violation
781 RRD_chk := NOW;
782 Previous_bank := TO_BITVECTOR (Ba);
783 END IF;
784
785 -- Precharge Block
786 IF Prech_enable = '1' THEN
787 IF Addr(10) = '1' THEN
788 Pc_b0 := '1';
789 Pc_b1 := '1';
790 Pc_b2 := '1';
791 Pc_b3 := '1';
792 Act_b0 := '0';
793 Act_b1 := '0';
794 Act_b2 := '0';
795 Act_b3 := '0';
796 RP_chk0 := NOW;
797 RP_chk1 := NOW;
798 RP_chk2 := NOW;
799 RP_chk3 := NOW;
800 -- Activate to Precharge all banks
801 ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS))
802 REPORT "tRAS violation during Precharge all banks"
803 SEVERITY WARNING;
804 -- tWR violation check for Write
805 IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR
806 (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN
807 ASSERT (FALSE)
808 REPORT "tWR violation during Precharge ALL banks"
809 SEVERITY WARNING;
810 END IF;
811 ELSIF Addr(10) = '0' THEN
812 IF Ba = "00" THEN
813 Pc_b0 := '1';
814 Act_b0 := '0';
815 RP_chk0 := NOW;
816 -- Activate to Precharge bank 0
817 ASSERT (NOW - RAS_chk0 >= tRAS)
818 REPORT "tRAS violation during Precharge bank 0"
819 SEVERITY WARNING;
820 ELSIF Ba = "01" THEN
821 Pc_b1 := '1';
822 Act_b1 := '0';
823 RP_chk1 := NOW;
824 -- Activate to Precharge bank 1
825 ASSERT (NOW - RAS_chk1 >= tRAS)
826 REPORT "tRAS violation during Precharge bank 1"
827 SEVERITY WARNING;
828 ELSIF Ba = "10" THEN
829 Pc_b2 := '1';
830 Act_b2 := '0';
831 RP_chk2 := NOW;
832 -- Activate to Precharge bank 2
833 ASSERT (NOW - RAS_chk2 >= tRAS)
834 REPORT "tRAS violation during Precharge bank 2"
835 SEVERITY WARNING;
836 ELSIF Ba = "11" THEN
837 Pc_b3 := '1';
838 Act_b3 := '0';
839 RP_chk3 := NOW;
840 -- Activate to Precharge bank 3
841 ASSERT (NOW - RAS_chk3 >= tRAS)
842 REPORT "tRAS violation during Precharge bank 3"
843 SEVERITY WARNING;
844 END IF;
845 -- tWR violation check for Write
846 ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp)
847 REPORT "tWR violation during Precharge"
848 SEVERITY WARNING;
849 END IF;
850 -- Terminate a Write Immediately (if same bank or all banks)
851 IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN
852 Data_in_enable := '0';
853 END IF;
854 -- Precharge Command Pipeline for READ
855 IF CAS_latency_3 = '1' THEN
856 Command(2) := PRECH;
857 Bank_precharge(2) := TO_BITVECTOR (Ba);
858 A10_precharge(2) := TO_BIT(Addr(10));
859 ELSIF CAS_latency_2 = '1' THEN
860 Command(1) := PRECH;
861 Bank_precharge(1) := TO_BITVECTOR (Ba);
862 A10_precharge(1) := TO_BIT(Addr(10));
863 END IF;
864 END IF;
865
866 -- Burst Terminate
867 IF Burst_term = '1' THEN
868 -- Terminate a Write immediately
869 IF Data_in_enable = '1' THEN
870 Data_in_enable := '0';
871 END IF;
872 -- Terminate a Read depend on CAS Latency
873 IF CAS_latency_3 = '1' THEN
874 Command(2) := BST;
875 ELSIF CAS_latency_2 = '1' THEN
876 Command(1) := BST;
877 END IF;
878 END IF;
879
880 -- Read, Write, Column Latch
881 IF Read_enable = '1' OR Write_enable = '1' THEN
882 -- Check to see if bank is open (ACT) for Read or Write
883 IF ((Ba="00" AND Pc_b0='1') OR (Ba="01" AND Pc_b1='1') OR (Ba="10" AND Pc_b2='1') OR (Ba="11" AND Pc_b3='1')) THEN
884 ASSERT (FALSE)
885 REPORT "Cannot Read or Write - Bank is not Activated"
886 SEVERITY WARNING;
887 END IF;
888 -- Activate to Read or Write
889 IF Ba = "00" THEN
890 ASSERT (NOW - RCD_chk0 >= tRCD)
891 REPORT "tRCD violation during Read or Write to Bank 0"
892 SEVERITY WARNING;
893 ELSIF Ba = "01" THEN
894 ASSERT (NOW - RCD_chk1 >= tRCD)
895 REPORT "tRCD violation during Read or Write to Bank 1"
896 SEVERITY WARNING;
897 ELSIF Ba = "10" THEN
898 ASSERT (NOW - RCD_chk2 >= tRCD)
899 REPORT "tRCD violation during Read or Write to Bank 2"
900 SEVERITY WARNING;
901 ELSIF Ba = "11" THEN
902 ASSERT (NOW - RCD_chk3 >= tRCD)
903 REPORT "tRCD violation during Read or Write to Bank 3"
904 SEVERITY WARNING;
905 END IF;
906
907 -- Read Command
908 IF Read_enable = '1' THEN
909 -- CAS Latency Pipeline
910 IF Cas_latency_3 = '1' THEN
911 IF Addr(10) = '1' THEN
912 Command(2) := READ_A;
913 ELSE
914 Command(2) := READ;
915 END IF;
916 Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
917 Bank_addr (2) := TO_BITVECTOR (Ba);
918 ELSIF Cas_latency_2 = '1' THEN
919 IF Addr(10) = '1' THEN
920 Command(1) := READ_A;
921 ELSE
922 Command(1) := READ;
923 END IF;
924 Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
925 Bank_addr (1) := TO_BITVECTOR (Ba);
926 END IF;
927
928 -- Read intterupt a Write (terminate Write immediately)
929 IF Data_in_enable = '1' THEN
930 Data_in_enable := '0';
931 END IF;
932
933 -- Write Command
934 ELSIF Write_enable = '1' THEN
935 IF Addr(10) = '1' THEN
936 Command(0) := WRITE_A;
937 ELSE
938 Command(0) := WRITE;
939 END IF;
940 Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0));
941 Bank_addr (0) := TO_BITVECTOR (Ba);
942
943 -- Write intterupt a Write (terminate Write immediately)
944 IF Data_in_enable = '1' THEN
945 Data_in_enable := '0';
946 END IF;
947
948 -- Write interrupt a Read (terminate Read immediately)
949 IF Data_out_enable = '1' THEN
950 Data_out_enable := '0';
951 END IF;
952 END IF;
953
954 -- Interrupt a Write with Auto Precharge
955 IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Write_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN
956 RW_interrupt_write(TO_INTEGER(RW_Interrupt_Bank)) := '1';
957 END IF;
958
959 -- Interrupt a Read with Auto Precharge
960 IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Read_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN
961 RW_interrupt_read(TO_INTEGER(RW_Interrupt_Bank)) := '1';
962 END IF;
963
964 -- Read or Write with Auto Precharge
965 IF Addr(10) = '1' THEN
966 Auto_precharge (TO_INTEGER(Ba)) := '1';
967 Count_precharge (TO_INTEGER(Ba)) := 0;
968 RW_Interrupt_Bank := TO_BitVector(Ba);
969 IF Read_enable = '1' THEN
970 Read_precharge (TO_INTEGER(Ba)) := '1';
971 ELSIF Write_enable = '1' THEN
972 Write_precharge (TO_INTEGER(Ba)) := '1';
973 END IF;
974 END IF;
975 END IF;
976
977 -- Read with AutoPrecharge Calculation
978 -- The device start internal precharge when:
979 -- 1. BL/2 cycles after command
980 -- and 2. Meet tRAS requirement
981 -- or 3. Interrupt by a Read or Write (with or without Auto Precharge)
982 IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN
983 IF (((NOW - RAS_chk0 >= tRAS) AND
984 ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR
985 (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR
986 (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR
987 (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR
988 (RW_interrupt_read(0) = '1')) THEN
989 Pc_b0 := '1';
990 Act_b0 := '0';
991 RP_chk0 := NOW;
992 Auto_precharge(0) := '0';
993 Read_precharge(0) := '0';
994 RW_interrupt_read(0) := '0';
995 END IF;
996 END IF;
997 IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN
998 IF (((NOW - RAS_chk1 >= tRAS) AND
999 ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR
1000 (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR
1001 (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR
1002 (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR
1003 (RW_interrupt_read(1) = '1')) THEN
1004 Pc_b1 := '1';
1005 Act_b1 := '0';
1006 RP_chk1 := NOW;
1007 Auto_precharge(1) := '0';
1008 Read_precharge(1) := '0';
1009 RW_interrupt_read(1) := '0';
1010 END IF;
1011 END IF;
1012 IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN
1013 IF (((NOW - RAS_chk2 >= tRAS) AND
1014 ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR
1015 (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR
1016 (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR
1017 (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR
1018 (RW_interrupt_read(2) = '1')) THEN
1019 Pc_b2 := '1';
1020 Act_b2 := '0';
1021 RP_chk2 := NOW;
1022 Auto_precharge(2) := '0';
1023 Read_precharge(2) := '0';
1024 RW_interrupt_read(2) := '0';
1025 END IF;
1026 END IF;
1027 IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN
1028 IF (((NOW - RAS_chk3 >= tRAS) AND
1029 ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR
1030 (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR
1031 (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR
1032 (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR
1033 (RW_interrupt_read(3) = '1')) THEN
1034 Pc_b3 := '1';
1035 Act_b3 := '0';
1036 RP_chk3 := NOW;
1037 Auto_precharge(3) := '0';
1038 Read_precharge(3) := '0';
1039 RW_interrupt_read(3) := '0';
1040 END IF;
1041 END IF;
1042
1043 -- Internal Precharge or Bst
1044 IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks
1045 IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN
1046 IF Data_out_enable = '1' THEN
1047 Data_out_enable := '0';
1048 END IF;
1049 END IF;
1050 ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank
1051 IF Data_out_enable = '1' THEN
1052 Data_out_enable := '0';
1053 END IF;
1054 END IF;
1055
1056 IF Data_out_enable = '0' THEN
1057 Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH;
1058 END IF;
1059
1060 -- Detect Read or Write Command
1061 IF Command(0) = READ OR Command(0) = READ_A THEN
1062 Bank := Bank_addr (0);
1063 Col := Col_addr (0);
1064 Col_brst := Col_addr (0);
1065 IF Bank_addr (0) = "00" THEN
1066 Row := B0_row_addr;
1067 ELSIF Bank_addr (0) = "01" THEN
1068 Row := B1_row_addr;
1069 ELSIF Bank_addr (0) = "10" THEN
1070 Row := B2_row_addr;
1071 ELSE
1072 Row := B3_row_addr;
1073 END IF;
1074 Burst_counter := 0;
1075 Data_in_enable := '0';
1076 Data_out_enable := '1';
1077 ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN
1078 Bank := Bank_addr(0);
1079 Col := Col_addr(0);
1080 Col_brst := Col_addr(0);
1081 IF Bank_addr (0) = "00" THEN
1082 Row := B0_row_addr;
1083 ELSIF Bank_addr (0) = "01" THEN
1084 Row := B1_row_addr;
1085 ELSIF Bank_addr (0) = "10" THEN
1086 Row := B2_row_addr;
1087 ELSE
1088 Row := B3_row_addr;
1089 END IF;
1090 Burst_counter := 0;
1091 Data_in_enable := '1';
1092 Data_out_enable := '0';
1093 END IF;
1094
1095 -- DQ (Driver / Receiver)
1096 Row_index := TO_INTEGER (Row);
1097 Col_index := TO_INTEGER (Col);
1098 IF Data_in_enable = '1' THEN
1099 IF Dqm /= "11" THEN
1100 Init_mem (Bank, Row_index);
1101 IF Bank = "00" THEN
1102 Dq_temp := Bank0 (Row_index) (Col_index);
1103 IF Dqm = "01" THEN
1104 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1105 ELSIF Dqm = "10" THEN
1106 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1107 ELSE
1108 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1109 END IF;
1110 Bank0 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1111 ELSIF Bank = "01" THEN
1112 Dq_temp := Bank1 (Row_index) (Col_index);
1113 IF Dqm = "01" THEN
1114 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1115 ELSIF Dqm = "10" THEN
1116 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1117 ELSE
1118 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1119 END IF;
1120 Bank1 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1121 ELSIF Bank = "10" THEN
1122 Dq_temp := Bank2 (Row_index) (Col_index);
1123 IF Dqm = "01" THEN
1124 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1125 ELSIF Dqm = "10" THEN
1126 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1127 ELSE
1128 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1129 END IF;
1130 Bank2 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1131 ELSIF Bank = "11" THEN
1132 Dq_temp := Bank3 (Row_index) (Col_index);
1133 IF Dqm = "01" THEN
1134 Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8));
1135 ELSIF Dqm = "10" THEN
1136 Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0));
1137 ELSE
1138 Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0));
1139 END IF;
1140 Bank3 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0));
1141 END IF;
1142 WR_chkp(TO_INTEGER(Bank)) := NOW;
1143 WR_counter(TO_INTEGER(Bank)) := 0;
1144 END IF;
1145 Burst_decode;
1146 ELSIF Data_out_enable = '1' THEN
1147 IF Dqm_reg0 /= "11" THEN
1148 Init_mem (Bank, Row_index);
1149 IF Bank = "00" THEN
1150 Dq_temp := Bank0 (Row_index) (Col_index);
1151 IF Dqm_reg0 = "00" THEN
1152 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1153 ELSIF Dqm_reg0 = "01" THEN
1154 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1155 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1156 ELSIF Dqm_reg0 = "10" THEN
1157 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1158 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1159 END IF;
1160 ELSIF Bank = "01" THEN
1161 Dq_temp := Bank1 (Row_index) (Col_index);
1162 IF Dqm_reg0 = "00" THEN
1163 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1164 ELSIF Dqm_reg0 = "01" THEN
1165 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1166 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1167 ELSIF Dqm_reg0 = "10" THEN
1168 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1169 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1170 END IF;
1171 ELSIF Bank = "10" THEN
1172 Dq_temp := Bank2 (Row_index) (Col_index);
1173 IF Dqm_reg0 = "00" THEN
1174 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1175 ELSIF Dqm_reg0 = "01" THEN
1176 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1177 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1178 ELSIF Dqm_reg0 = "10" THEN
1179 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1180 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1181 END IF;
1182 ELSIF Bank = "11" THEN
1183 Dq_temp := Bank3 (Row_index) (Col_index);
1184 IF Dqm_reg0 = "00" THEN
1185 Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC;
1186 ELSIF Dqm_reg0 = "01" THEN
1187 Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC;
1188 Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1189 ELSIF Dqm_reg0 = "10" THEN
1190 Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC;
1191 Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC;
1192 END IF;
1193 END IF;
1194 ELSE
1195 Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ;
1196 END IF;
1197 Burst_decode;
1198 END IF;
1199 ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '1' AND Dump = '0' THEN --'
1200 Operation <= LOAD_FILE;
1201 load := '0';
1202 -- ASSERT (FALSE) REPORT "Reading memory array from file. This operation may take several minutes. Please wait..."
1203 -- SEVERITY NOTE;
1204 WHILE NOT endfile(file_load) LOOP
1205 readline(file_load, l);
1206 read(l, ch);
1207 if (ch /= 'S') or (ch /= 's') then
1208 hread(l, rectype);
1209 hread(l, reclen);
1210 recaddr := (others => '0');
1211 case rectype is
1212 when "0001" =>
1213 hread(l, recaddr(15 downto 0));
1214 when "0010" =>
1215 hread(l, recaddr(23 downto 0));
1216 when "0011" =>
1217 hread(l, recaddr);
1218 recaddr(31 downto 24) := (others => '0');
1219 when others => next;
1220 end case;
1221 hread(l, recdata);
1222
1223 if index < 32 then
1224 Bank_Load := recaddr(25 downto 24);
1225 Rows_Load := recaddr(23 downto 11);
1226 Cols_Load := recaddr(10 downto 2);
1227 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1228 IF Bank_Load = "00" THEN
1229 for i in 0 to 3 loop
1230 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1231 end loop;
1232 ELSIF Bank_Load = "01" THEN
1233 for i in 0 to 3 loop
1234 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1235 end loop;
1236 ELSIF Bank_Load = "10" THEN
1237 for i in 0 to 3 loop
1238 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1239 end loop;
1240 ELSIF Bank_Load = "11" THEN
1241 for i in 0 to 3 loop
1242 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*32+index to i*32+index+15));
1243 end loop;
1244 END IF;
1245 elsif(index < 1024) then
1246 Bank_Load := recaddr(26 downto 25);
1247 Rows_Load := recaddr(24 downto 12);
1248 Cols_Load := recaddr(11 downto 3);
1249 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1250 IF Bank_Load = "00" THEN
1251 for i in 0 to 1 loop
1252 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1253 end loop;
1254 ELSIF Bank_Load = "01" THEN
1255 for i in 0 to 1 loop
1256 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1257 end loop;
1258 ELSIF Bank_Load = "10" THEN
1259 for i in 0 to 1 loop
1260 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1261 end loop;
1262 ELSIF Bank_Load = "11" THEN
1263 for i in 0 to 1 loop
1264 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*64+index-32 to i*64+index-32+15));
1265 end loop;
1266 END IF;
1267 else
1268 Bank_Load := recaddr(22 downto 21);
1269 Rows_Load := '0' & recaddr(20 downto 9);
1270 Cols_Load := '0' & recaddr(8 downto 1);
1271 Init_Mem (Bank_Load, To_Integer(Rows_Load));
1272 IF Bank_Load = "00" THEN
1273 for i in 0 to 7 loop
1274 Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1275 end loop;
1276 ELSIF Bank_Load = "01" THEN
1277 for i in 0 to 7 loop
1278 Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1279 end loop;
1280 ELSIF Bank_Load = "10" THEN
1281 for i in 0 to 7 loop
1282 Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1283 end loop;
1284 ELSIF Bank_Load = "11" THEN
1285 for i in 0 to 7 loop
1286 Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)+i) := ('1' & recdata(i*16 to i*16+15));
1287 end loop;
1288 END IF;
1289 END IF;
1290 END IF;
1291 END LOOP;
1292 ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '1' THEN --'
1293 Operation <= DUMP_FILE;
1294 ASSERT (FALSE) REPORT "Writing memory array to file. This operation may take several minutes. Please wait..."
1295 SEVERITY NOTE;
1296 WRITE (l, string'("# Micron Technology, Inc. (FILE DUMP / MEMORY DUMP)")); --'
1297 WRITELINE (file_dump, l);
1298 WRITE (l, string'("# BA ROWS COLS DQ")); --'
1299 WRITELINE (file_dump, l);
1300 WRITE (l, string'("# -- ------------- --------- ----------------")); --'
1301 WRITELINE (file_dump, l);
1302 -- Dumping Bank 0
1303 FOR i IN 0 TO 2**addr_bits -1 LOOP
1304 -- Check if ROW is NULL
1305 IF Bank0 (i) /= NULL THEN
1306 For j IN 0 TO 2**col_bits - 1 LOOP
1307 -- Check if COL is NULL
1308 NEXT WHEN Bank0 (i) (j) (data_bits) = '0';
1309 WRITE (l, string'("00"), right, 4); --'
1310 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1311 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1312 WRITE (l, Bank0 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1313 WRITELINE (file_dump, l);
1314 END LOOP;
1315 END IF;
1316 END LOOP;
1317 -- Dumping Bank 1
1318 FOR i IN 0 TO 2**addr_bits -1 LOOP
1319 -- Check if ROW is NULL
1320 IF Bank1 (i) /= NULL THEN
1321 For j IN 0 TO 2**col_bits - 1 LOOP
1322 -- Check if COL is NULL
1323 NEXT WHEN Bank1 (i) (j) (data_bits) = '0';
1324 WRITE (l, string'("01"), right, 4); --'
1325 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1326 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1327 WRITE (l, Bank1 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1328 WRITELINE (file_dump, l);
1329 END LOOP;
1330 END IF;
1331 END LOOP;
1332 -- Dumping Bank 2
1333 FOR i IN 0 TO 2**addr_bits -1 LOOP
1334 -- Check if ROW is NULL
1335 IF Bank2 (i) /= NULL THEN
1336 For j IN 0 TO 2**col_bits - 1 LOOP
1337 -- Check if COL is NULL
1338 NEXT WHEN Bank2 (i) (j) (data_bits) = '0';
1339 WRITE (l, string'("10"), right, 4); --'
1340 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1341 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1342 WRITE (l, Bank2 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1343 WRITELINE (file_dump, l);
1344 END LOOP;
1345 END IF;
1346 END LOOP;
1347 -- Dumping Bank 3
1348 FOR i IN 0 TO 2**addr_bits -1 LOOP
1349 -- Check if ROW is NULL
1350 IF Bank3 (i) /= NULL THEN
1351 For j IN 0 TO 2**col_bits - 1 LOOP
1352 -- Check if COL is NULL
1353 NEXT WHEN Bank3 (i) (j) (data_bits) = '0';
1354 WRITE (l, string'("11"), right, 4); --'
1355 WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1);
1356 WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1);
1357 WRITE (l, Bank3 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1);
1358 WRITELINE (file_dump, l);
1359 END LOOP;
1360 END IF;
1361 END LOOP;
1362 END IF;
1363
1364 -- Write with AutoPrecharge Calculation
1365 -- The device start internal precharge when:
1366 -- 1. tWR cycles after command
1367 -- and 2. Meet tRAS requirement
1368 -- or 3. Interrupt by a Read or Write (with or without Auto Precharge)
1369 IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN
1370 IF (((NOW - RAS_chk0 >= tRAS) AND
1371 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR
1372 (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR
1373 (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR
1374 (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR
1375 (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN
1376 Auto_precharge(0) := '0';
1377 Write_precharge(0) := '0';
1378 RW_interrupt_write(0) := '0';
1379 Pc_b0 := '1';
1380 Act_b0 := '0';
1381 RP_chk0 := NOW;
1382 ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE;
1383 END IF;
1384 END IF;
1385 IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN
1386 IF (((NOW - RAS_chk1 >= tRAS) AND
1387 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR
1388 (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR
1389 (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR
1390 (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR
1391 (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN
1392 Auto_precharge(1) := '0';
1393 Write_precharge(1) := '0';
1394 RW_interrupt_write(1) := '0';
1395 Pc_b1 := '1';
1396 Act_b1 := '0';
1397 RP_chk1 := NOW;
1398 END IF;
1399 END IF;
1400 IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN
1401 IF (((NOW - RAS_chk2 >= tRAS) AND
1402 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR
1403 (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR
1404 (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR
1405 (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR
1406 (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN
1407 Auto_precharge(2) := '0';
1408 Write_precharge(2) := '0';
1409 RW_interrupt_write(2) := '0';
1410 Pc_b2 := '1';
1411 Act_b2 := '0';
1412 RP_chk2 := NOW;
1413 END IF;
1414 END IF;
1415 IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN
1416 IF (((NOW - RAS_chk3 >= tRAS) AND
1417 (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR
1418 (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR
1419 (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR
1420 (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR
1421 (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN
1422 Auto_precharge(3) := '0';
1423 Write_precharge(3) := '0';
1424 RW_interrupt_write(3) := '0';
1425 Pc_b3 := '1';
1426 Act_b3 := '0';
1427 RP_chk3 := NOW;
1428 END IF;
1429 END IF;
1430
1431 -- Checking internal wires (Optional for debug purpose)
1432 Pre_chk (0) <= Pc_b0;
1433 Pre_chk (1) <= Pc_b1;
1434 Pre_chk (2) <= Pc_b2;
1435 Pre_chk (3) <= Pc_b3;
1436 Act_chk (0) <= Act_b0;
1437 Act_chk (1) <= Act_b1;
1438 Act_chk (2) <= Act_b2;
1439 Act_chk (3) <= Act_b3;
1440 Dq_in_chk <= Data_in_enable;
1441 Dq_out_chk <= Data_out_enable;
1442 Bank_chk <= Bank;
1443 Row_chk <= Row;
1444 Col_chk <= Col;
1445 END PROCESS;
1446
1447
1448 -- Clock timing checks
1449 -- Clock_check : PROCESS
1450 -- VARIABLE Clk_low, Clk_high : TIME := 0 ns;
1451 -- BEGIN
1452 -- WAIT ON Clk;
1453 -- IF (Clk = '1' AND NOW >= 10 ns) THEN
1454 -- ASSERT (NOW - Clk_low >= tCL)
1455 -- REPORT "tCL violation"
1456 -- SEVERITY WARNING;
1457 -- ASSERT (NOW - Clk_high >= tCK)
1458 -- REPORT "tCK violation"
1459 -- SEVERITY WARNING;
1460 -- Clk_high := NOW;
1461 -- ELSIF (Clk = '0' AND NOW /= 0 ns) THEN
1462 -- ASSERT (NOW - Clk_high >= tCH)
1463 -- REPORT "tCH violation"
1464 -- SEVERITY WARNING;
1465 -- Clk_low := NOW;
1466 -- END IF;
1467 -- END PROCESS;
1468
1469 -- Setup timing checks
1470 Setup_check : PROCESS
1471 BEGIN
1472 wait;
1473 WAIT ON Clk;
1474 IF Clk = '1' THEN
1475 ASSERT(Cke'LAST_EVENT >= tCKS) --'
1476 REPORT "CKE Setup time violation -- tCKS"
1477 SEVERITY WARNING;
1478 ASSERT(Cs_n'LAST_EVENT >= tCMS) --'
1479 REPORT "CS# Setup time violation -- tCMS"
1480 SEVERITY WARNING;
1481 ASSERT(Cas_n'LAST_EVENT >= tCMS) --'
1482 REPORT "CAS# Setup time violation -- tCMS"
1483 SEVERITY WARNING;
1484 ASSERT(Ras_n'LAST_EVENT >= tCMS) --'
1485 REPORT "RAS# Setup time violation -- tCMS"
1486 SEVERITY WARNING;
1487 ASSERT(We_n'LAST_EVENT >= tCMS) --'
1488 REPORT "WE# Setup time violation -- tCMS"
1489 SEVERITY WARNING;
1490 ASSERT(Dqm'LAST_EVENT >= tCMS) --'
1491 REPORT "Dqm Setup time violation -- tCMS"
1492 SEVERITY WARNING;
1493 ASSERT(Addr'LAST_EVENT >= tAS) --'
1494 REPORT "ADDR Setup time violation -- tAS"
1495 SEVERITY WARNING;
1496 ASSERT(Ba'LAST_EVENT >= tAS) --'
1497 REPORT "BA Setup time violation -- tAS"
1498 SEVERITY WARNING;
1499 ASSERT(Dq'LAST_EVENT >= tDS) --'
1500 REPORT "Dq Setup time violation -- tDS"
1501 SEVERITY WARNING;
1502 END IF;
1503 END PROCESS;
1504
1505 -- Hold timing checks
1506 Hold_check : PROCESS
1507 BEGIN
1508 wait;
1509 WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH);
1510 IF Clk'DELAYED (tCKH) = '1' THEN --'
1511 ASSERT(Cke'LAST_EVENT > tCKH) --'
1512 REPORT "CKE Hold time violation -- tCKH"
1513 SEVERITY WARNING;
1514 END IF;
1515 IF Clk'DELAYED (tCMH) = '1' THEN --'
1516 ASSERT(Cs_n'LAST_EVENT > tCMH) --'
1517 REPORT "CS# Hold time violation -- tCMH"
1518 SEVERITY WARNING;
1519 ASSERT(Cas_n'LAST_EVENT > tCMH) --'
1520 REPORT "CAS# Hold time violation -- tCMH"
1521 SEVERITY WARNING;
1522 ASSERT(Ras_n'LAST_EVENT > tCMH) --'
1523 REPORT "RAS# Hold time violation -- tCMH"
1524 SEVERITY WARNING;
1525 ASSERT(We_n'LAST_EVENT > tCMH) --'
1526 REPORT "WE# Hold time violation -- tCMH"
1527 SEVERITY WARNING;
1528 ASSERT(Dqm'LAST_EVENT > tCMH) --'
1529 REPORT "Dqm Hold time violation -- tCMH"
1530 SEVERITY WARNING;
1531 END IF;
1532 IF Clk'DELAYED (tAH) = '1' THEN --'
1533 ASSERT(Addr'LAST_EVENT > tAH) --'
1534 REPORT "ADDR Hold time violation -- tAH"
1535 SEVERITY WARNING;
1536 ASSERT(Ba'LAST_EVENT > tAH) --'
1537 REPORT "BA Hold time violation -- tAH"
1538 SEVERITY WARNING;
1539 END IF;
1540 IF Clk'DELAYED (tDH) = '1' THEN --'
1541 ASSERT(Dq'LAST_EVENT > tDH) --'
1542 REPORT "Dq Hold time violation -- tDH"
1543 SEVERITY WARNING;
1544 END IF;
1545 END PROCESS;
1546
1547 END behave;
1548
1549 -- pragma translate_on
1550
@@ -0,0 +1,69
1 <?xml version='1.0' encoding='utf-8'?>
2 <soc name="Leon">
3 <peripheral vid="8" name="SpaceWire Light" pid="305">
4 <register name="Control register" addOffset="0">
5 <bitField size="1" offset="0" name="Reset" mode="3" desc="Write '1' to reset SPWAMBA core (auto-clear)."/>
6 <bitField size="1" offset="1" name="Reset DMA" mode="3" desc="Write '1' to reset DMA engines (auto-clear)."/>
7 <bitField name="Link Start" offset="2" size="1" mode="3" desc="Link start signal. '1' = actively try to start a SpaceWire link."/>
8 <bitField name="Link Auto Start" offset="3" size="1" mode="3" desc="Link autostart signal. '1' = start link after receiving NULL from other side."/>
9 <bitField name="Link Disable" offset="4" size="1" mode="3" desc="Link disable signal. '1' = shut down current link and do not establish new link."/>
10 <bitField name="Time Code EN" offset="5" size="1" mode="3" desc="Allow time-code transmission through tick_in signal."/>
11 <bitField name="Restart RX DMA" offset="6" size="1" mode="3" desc="Write '1' to (re-)start RX DMA (auto-clear)."/>
12 <bitField name="Restart TX DMA" offset="7" size="1" mode="3" desc="Write '1' to (re-)start TX DMA (auto-clear)."/>
13 <bitField name="Cancel TX DMA" offset="8" size="1" mode="3" desc="Write '1' to cancel running TX DMA and discard data from TX FIFO (auto-clear)."/>
14 <bitField name="Link Up/Down IE" offset="9" size="1" mode="3" desc="Enable interrupt on link up/down."/>
15 <bitField name="Time Code IE" offset="10" size="1" mode="3" desc="Enable interrupt on time code received."/>
16 <bitField name="RXDESCIE" offset="11" size="1" mode="3" desc="Enable interrupt on completed RX descriptor with IE='1'."/>
17 <bitField name="TXDESCIE" offset="12" size="1" mode="3" desc="Enable interrupt on completed TX descriptor with IE='1'."/>
18 <bitField name="RXIE" offset="13" size="1" mode="3" desc="Enable interrupt on RX packet received."/>
19 <bitField name="DescSz" offset="24" size="4" mode="1" desc="Value of desctablesize generic (read-only)."/>
20 </register>
21 <register name="Status register" addOffset="4">
22 <bitField size="2" offset="0" name="LSTAT" mode="1" desc="Link status: 0=off, 1=started, 2=connecting, 3=run (read-only)."/>
23 <bitField size="1" offset="2" name="DISCERR" mode="3" desc="Got disconnect error (sticky, write '1' to clear)."/>
24 <bitField size="1" offset="3" name="PARERR" mode="3" desc="Got parity error (sticky, write '1' to clear)."/>
25 <bitField size="1" offset="4" name="ESCERR" mode="3" desc="Got escape error (sticky, write '1' to clear)."/>
26 <bitField size="1" offset="5" name="CREDERR" mode="3" desc="Got credit error (sticky, write '1' to clear)."/>
27 <bitField size="1" offset="6" name="RXDMA" mode="1" desc="RX DMA running (read-only)."/>
28 <bitField size="1" offset="7" name="RXDMA" mode="1" desc="TX DMA running (read-only)."/>
29 <bitField size="1" offset="8" name="AHBERR" mode="1" desc="AHB error occurred (sticky, reset DMA engine to clear)."/>
30 <bitField size="1" offset="9" name="UNUSED" mode="3" desc="unused"/>
31 <bitField size="1" offset="10" name="TIMECODE" mode="3" desc="Received time-code (sticky, write '1' to clear)."/>
32 <bitField size="1" offset="11" name="RXDESCCOMP" mode="3" desc="Completed RX descriptor with IE='1' (sticky, write '1' to clear)."/>
33 <bitField size="1" offset="12" name="TXDESCCOMP" mode="3" desc="Completed TX descriptor with IE='1' (sticky, write '1' to clear)."/>
34 <bitField size="1" offset="13" name="RECPACKT" mode="3" desc="Received packet (sticky, write '1' to clear)."/>
35 <bitField size="1" offset="14" name="RXE" mode="1" desc="RX buffer is empty and last packet has been completely transfered to RX DMA (read-only)."/>
36 </register>
37 <register name="Transmission clock scaler" addOffset="8">
38 <bitField size="8" offset="0" name="N" mode="3" desc="Clock division factor minus 1. The actual TX bit rate is determined by (txclk frequency) / (scaler + 1).
39 During the handshake phase, this register is ignored and the TX bit rate is forced to 10 Mbit. After reset, this
40 register defaults to the scaler value needed for 10 Mbit."/>
41 </register>
42 <register name="Time-code register" addOffset="12">
43 <bitField size="6" offset="0" name="Address" mode="1" desc="Last received time-code value (read-only)."/>
44 <bitField size="2" offset="6" name="Address" mode="1" desc="Control bits received with last time-code (read-only)."/>
45 <bitField size="6" offset="12" name="Address" mode="3" desc="Time-code value to send on next tick_in (auto-increment)."/>
46 <bitField size="2" offset="14" name="Address" mode="3" desc="Reserved, write as zero."/>
47 <bitField size="1" offset="15" name="Address" mode="3" desc="Write '1' to send a time-code immediately (auto-clear)."/>
48 </register>
49 <register name="Descriptor pointer for RX DMA" addOffset="16">
50 <bitField size="3" offset="0" name="DATA" mode="3" desc="Reserved, write as zero."/>
51 <bitField size="10" offset="3" name="DATA" mode="3" desc="Descriptor index (auto-increment)."/>
52 <bitField size="19" offset="13" name="DATA" mode="3" desc="Fixed address bits of descriptor table."/>
53 </register>
54 <register name="Descriptor pointer for TX DMA" addOffset="20">
55 <bitField size="3" offset="0" name="DATA" mode="3" desc="Reserved, write as zero."/>
56 <bitField size="10" offset="3" name="DATA" mode="3" desc="Descriptor index (auto-increment)."/>
57 <bitField size="19" offset="13" name="DATA" mode="3" desc="Fixed address bits of descriptor table."/>
58 </register>
59 </peripheral>
60 </soc>
61
62
63
64
65
66
67
68
69
This diff has been collapsed as it changes many lines, (1053 lines changed) Show them Hide them
@@ -0,0 +1,1053
1 ------------------------------------------------------------------------------
2 -- This file is a part of the GRLIB VHDL IP LIBRARY
3 -- Copyright (C) 2003 - 2008, Gaisler Research
4 -- Copyright (C) 2008 - 2014, Aeroflex Gaisler
5 -- Copyright (C) 2015 - 2016, Cobham Gaisler
6 --
7 -- This program is free software; you can redistribute it and/or modify
8 -- it under the terms of the GNU General Public License as published by
9 -- the Free Software Foundation; either version 2 of the License, or
10 -- (at your option) any later version.
11 --
12 -- This program is distributed in the hope that it will be useful,
13 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 -- GNU General Public License for more details.
16 --
17 -- You should have received a copy of the GNU General Public License
18 -- along with this program; if not, write to the Free Software
19 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 -----------------------------------------------------------------------------
21 -- Entity: sdctrl16
22 -- File: sdctrl16.vhd
23 -- Author: Jiri Gaisler - Gaisler Research
24 -- Modified by: Daniel Bengtsson & Richard Fång
25 -- Description: 16- and 32-bit SDRAM memory controller.
26 ------------------------------------------------------------------------------
27
28 library ieee;
29 use ieee.std_logic_1164.all;
30 library grlib;
31 use grlib.amba.all;
32 use grlib.stdlib.all;
33 library gaisler;
34 use grlib.devices.all;
35 use gaisler.memctrl.all;
36
37 entity sdctrl16 is
38 generic (
39 hindex : integer := 0;
40 haddr : integer := 0;
41 hmask : integer := 16#f00#;
42 ioaddr : integer := 16#000#;
43 iomask : integer := 16#fff#;
44 wprot : integer := 0;
45 invclk : integer := 0;
46 fast : integer := 0;
47 pwron : integer := 0;
48 sdbits : integer := 16;
49 oepol : integer := 0;
50 pageburst : integer := 0;
51 mobile : integer := 0
52 );
53 port (
54 rst : in std_ulogic;
55 clk : in std_ulogic;
56 ahbsi : in ahb_slv_in_type;
57 ahbso : out ahb_slv_out_type;
58 sdi : in sdctrl_in_type;
59 sdo : out sdctrl_out_type
60 );
61 end;
62
63 architecture rtl of sdctrl16 is
64
65 constant WPROTEN : boolean := wprot = 1;
66 constant SDINVCLK : boolean := invclk = 1;
67 constant BUS16 : boolean := (sdbits = 16);
68 constant BUS32 : boolean := (sdbits = 32);
69 constant BUS64 : boolean := (sdbits = 64);
70
71 constant REVISION : integer := 1;
72
73 constant PM_PD : std_logic_vector(2 downto 0) := "001";
74 constant PM_SR : std_logic_vector(2 downto 0) := "010";
75 constant PM_DPD : std_logic_vector(2 downto 0) := "101";
76
77 constant std_rammask: Std_Logic_Vector(31 downto 20) :=
78 Conv_Std_Logic_Vector(hmask, 12);
79
80 constant hconfig : ahb_config_type := (
81 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_SDCTRL, 0, REVISION, 0),
82 4 => ahb_membar(haddr, '1', '1', hmask),
83 5 => ahb_iobar(ioaddr, iomask),
84 others => zero32);
85
86 type mcycletype is (midle, active, leadout);
87 type sdcycletype is (act1, act2, act3, act3_16, rd1, rd2, rd3, rd4, rd4_16, rd5, rd6, rd7, rd8,
88 wr1, wr1_16, wr2, wr3, wr4, wr5, sidle,
89 sref, pd, dpd);
90 type icycletype is (iidle, pre, ref, lmode, emode, finish);
91
92 -- sdram configuration register
93
94 type sdram_cfg_type is record
95 command : std_logic_vector(2 downto 0);
96 csize : std_logic_vector(1 downto 0);
97 bsize : std_logic_vector(2 downto 0);
98 casdel : std_ulogic; -- CAS to data delay: 2/3 clock cycles
99 trfc : std_logic_vector(2 downto 0);
100 trp : std_ulogic; -- precharge to activate: 2/3 clock cycles
101 refresh : std_logic_vector(14 downto 0);
102 renable : std_ulogic;
103 pageburst : std_ulogic;
104 mobileen : std_logic_vector(1 downto 0); -- Mobile SD support, Mobile SD enabled
105 ds : std_logic_vector(3 downto 0); -- ds(1:0) (ds(3:2) used to detect update)
106 tcsr : std_logic_vector(3 downto 0); -- tcrs(1:0) (tcrs(3:2) used to detect update)
107 pasr : std_logic_vector(5 downto 0); -- pasr(2:0) (pasr(5:3) used to detect update)
108 pmode : std_logic_vector(2 downto 0); -- Power-Saving mode
109 txsr : std_logic_vector(3 downto 0); -- Exit Self Refresh timing
110 cke : std_ulogic; -- Clock enable
111 end record;
112
113 -- local registers
114
115 type reg_type is record
116 hready : std_ulogic;
117 hsel : std_ulogic;
118 bdrive : std_ulogic;
119 nbdrive : std_ulogic;
120 burst : std_ulogic;
121 wprothit : std_ulogic;
122 hio : std_ulogic;
123 startsd : std_ulogic;
124 lhw : std_ulogic; --Lower halfword
125
126 mstate : mcycletype;
127 sdstate : sdcycletype;
128 cmstate : mcycletype;
129 istate : icycletype;
130 icnt : std_logic_vector(2 downto 0);
131
132 haddr : std_logic_vector(31 downto 0);
133 hrdata : std_logic_vector((sdbits-1)+((16/sdbits)*16) downto 0);
134 hwdata : std_logic_vector(31 downto 0);
135 hwrite : std_ulogic;
136 htrans : std_logic_vector(1 downto 0);
137 hresp : std_logic_vector(1 downto 0);
138 size : std_logic_vector(1 downto 0);
139
140 cfg : sdram_cfg_type;
141 trfc : std_logic_vector(3 downto 0);
142 refresh : std_logic_vector(14 downto 0);
143 sdcsn : std_logic_vector(1 downto 0);
144 sdwen : std_ulogic;
145 rasn : std_ulogic;
146 casn : std_ulogic;
147 dqm : std_logic_vector(7 downto 0);
148 address : std_logic_vector(16 downto 2); -- memory address
149 bsel : std_ulogic;
150
151 idlecnt : std_logic_vector(3 downto 0); -- Counter, 16 idle clock sycles before entering Power-Saving mode
152 sref_tmpcom : std_logic_vector(2 downto 0); -- Save SD command when exit sref
153 end record;
154
155 signal r, ri : reg_type;
156 signal rbdrive, ribdrive : std_logic_vector(31 downto 0);
157 attribute syn_preserve : boolean;
158 attribute syn_preserve of rbdrive : signal is true;
159
160 begin
161
162 ctrl : process(rst, ahbsi, r, sdi, rbdrive)
163 variable v : reg_type; -- local variables for registers
164 variable startsd : std_ulogic;
165 variable dataout : std_logic_vector(31 downto 0); -- data from memory
166 variable regsd : std_logic_vector(31 downto 0); -- data from registers
167 variable dqm : std_logic_vector(7 downto 0);
168 variable raddr : std_logic_vector(12 downto 0);
169 variable adec : std_ulogic;
170 variable rams : std_logic_vector(1 downto 0);
171 variable ba : std_logic_vector(1 downto 0);
172 variable haddr : std_logic_vector(31 downto 0);
173 variable dout : std_logic_vector(31 downto 0);
174 variable hsize : std_logic_vector(1 downto 0);
175 variable hwrite : std_ulogic;
176 variable htrans : std_logic_vector(1 downto 0);
177 variable hready : std_ulogic;
178 variable vbdrive : std_logic_vector(31 downto 0);
179 variable bdrive : std_ulogic;
180 variable lline : std_logic_vector(2 downto 0);
181 variable lineburst : boolean;
182 variable haddr_tmp : std_logic_vector(31 downto 0);
183 variable arefresh : std_logic;
184 variable hwdata : std_logic_vector(31 downto 0);
185
186 begin
187
188 -- Variable default settings to avoid latches
189
190 v := r; startsd := '0'; v.hresp := HRESP_OKAY; vbdrive := rbdrive; arefresh := '0';
191 if BUS16 then
192 if (r.lhw = '1') then --muxes read data to correct part of the register.
193 v.hrdata(sdbits-1 downto 0) := sdi.data(sdbits-1 downto 0);
194 else
195 v.hrdata((sdbits*2)-1 downto sdbits) := sdi.data(sdbits-1 downto 0);
196 end if;
197 else
198 v.hrdata(sdbits-1 downto sdbits-32) := sdi.data(sdbits-1 downto sdbits-32);
199 v.hrdata(31 downto 0) := sdi.data(31 downto 0);
200 end if;
201 hwdata := ahbreadword(ahbsi.hwdata, r.haddr(4 downto 2)); v.hwdata := hwdata;
202 lline := not r.cfg.casdel & r.cfg.casdel & r.cfg.casdel;
203 if (pageburst = 0) or ((pageburst = 2) and r.cfg.pageburst = '0') then
204 lineburst := true;
205 else lineburst := false; end if;
206
207
208 if ((ahbsi.hready and ahbsi.hsel(hindex)) = '1') then
209 v.size := ahbsi.hsize(1 downto 0); v.hwrite := ahbsi.hwrite;
210 v.htrans := ahbsi.htrans;
211 if ahbsi.htrans(1) = '1' then
212 v.hio := ahbsi.hmbsel(1);
213 v.hsel := '1'; v.hready := v.hio;
214 end if;
215 v.haddr := ahbsi.haddr;
216 -- addr must be masked since address range can be smaller than
217 -- total banksize. this can result in wrong chip select being
218 -- asserted
219 for i in 31 downto 20 loop
220 v.haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
221 end loop;
222 end if;
223
224 if (r.hsel = '1') and (ahbsi.hready = '0') then
225 haddr := r.haddr; hsize := r.size;
226 htrans := r.htrans; hwrite := r.hwrite;
227 else
228 haddr := ahbsi.haddr; hsize := ahbsi.hsize(1 downto 0);
229 htrans := ahbsi.htrans; hwrite := ahbsi.hwrite;
230 -- addr must be masked since address range can be smaller than
231 -- total banksize. this can result in wrong chip select being
232 -- asserted
233 for i in 31 downto 20 loop
234 haddr(i) := ahbsi.haddr(i) and not std_rammask(i);
235 end loop;
236 end if;
237 if fast = 1 then haddr := r.haddr; end if;
238
239 if ahbsi.hready = '1' then v.hsel := ahbsi.hsel(hindex); end if;
240
241 -- main state
242 if BUS16 then
243 case r.size is
244 when "00" => --bytesize
245 case r.haddr(0) is
246 when '0' => dqm := "11111101";
247 when others => dqm := "11111110";
248 end case;
249 when others => dqm := "11111100"; --halfword, word
250 end case;
251 else
252 case r.size is
253 when "00" =>
254 case r.haddr(1 downto 0) is
255 when "00" => dqm := "11110111";
256 when "01" => dqm := "11111011";
257 when "10" => dqm := "11111101";
258 when others => dqm := "11111110";
259 end case;
260 when "01" =>
261 if r.haddr(1) = '0' then dqm := "11110011"; else dqm := "11111100"; end if;
262 when others => dqm := "11110000";
263 end case;
264 end if;
265 --
266 -- case r.size is
267 -- when "00" =>
268 -- case r.haddr(1 downto 0) is
269 -- when "00" => dqm := "11111101"; lhw := '0'; --lhv := r.haddr(1)
270 -- when "01" => dqm := "11111110"; lhw := '0';
271 -- when "10" => dqm := "11111101"; lhw := '1';
272 -- when others => dqm := "11111110"; lhw := '1';
273 -- end case;
274 -- when "01" =>
275 -- dqm := "11111100";
276 -- if r.haddr(1) = '0' then
277 -- lhw := '0';
278 -- else
279 -- lhw := '1';
280 -- end if;
281 -- when others => dqm := "11111100"; --remember when word: lhw first 0 then 1
282 -- end case;
283 --
284 if BUS64 and (r.bsel = '1') then dqm := dqm(3 downto 0) & "1111"; end if;
285
286 -- main FSM
287
288 case r.mstate is
289 when midle =>
290 if ((v.hsel and htrans(1) and not v.hio) = '1') then
291 if (r.sdstate = sidle) and (r.cfg.command = "000")
292 and (r.cmstate = midle) and (v.hio = '0')
293 then
294 if fast = 0 then startsd := '1'; else v.startsd := '1'; end if;
295 v.mstate := active;
296 elsif ((r.sdstate = sref) or (r.sdstate = pd) or (r.sdstate = dpd))
297 and (r.cfg.command = "000") and (r.cmstate = midle) and (v.hio = '0')
298 then
299 v.startsd := '1';
300 if r.sdstate = dpd then -- Error response when on Deep Power-Down mode
301 v.hresp := HRESP_ERROR;
302 else
303 v.mstate := active;
304 end if;
305 end if;
306 end if;
307 when others => null;
308 end case;
309
310 startsd := startsd or r.startsd;
311
312 -- generate row and column address size
313
314 if BUS16 then
315 case r.cfg.csize is
316 when "00" => raddr := haddr(21 downto 9);-- case to check for bursting over row limit, since 1 row is 512 byte.
317 when "01" => raddr := haddr(22 downto 10);
318 when "10" => raddr := haddr(23 downto 11);
319 when others =>
320 if r.cfg.bsize = "110" then raddr := haddr(25 downto 13); --tänk
321 else raddr := haddr(24 downto 12); end if;
322 end case;
323 else
324 case r.cfg.csize is
325 when "00" => raddr := haddr(22 downto 10);
326 when "01" => raddr := haddr(23 downto 11);
327 when "10" => raddr := haddr(24 downto 12);
328 when others =>
329 if r.cfg.bsize = "111" then raddr := haddr(26 downto 14);
330 else raddr := haddr(25 downto 13); end if;
331 end case;
332 end if;
333
334 -- generate bank address
335 -- if BUS16 then --011
336 -- ba := genmux(r.cfg.bsize, haddr(26 downto 19)) &
337 -- genmux(r.cfg.bsize, haddr(25 downto 18));
338 -- else
339 ba := genmux(r.cfg.bsize, haddr(28 downto 21)) &
340 genmux(r.cfg.bsize, haddr(27 downto 20));
341 -- end if;
342
343 -- generate chip select
344
345 if BUS64 then
346 adec := genmux(r.cfg.bsize, haddr(30 downto 23));
347 v.bsel := genmux(r.cfg.bsize, r.haddr(29 downto 22));
348 else
349 adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
350 end if;
351 -- elsif BUS32 then
352 -- adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0';
353 -- else
354 -- adec := genmux(r.cfg.bsize, haddr(27 downto 20)); v.bsel := '0';
355 -- end if;
356
357 rams := adec & not adec;
358
359 -- sdram access FSM
360
361 if r.trfc /= "0000" then v.trfc := r.trfc - 1; end if;
362
363 if r.idlecnt /= "0000" then v.idlecnt := r.idlecnt - 1; end if;
364
365 case r.sdstate is
366
367 when sidle =>
368 if (startsd = '1') and (r.cfg.command = "000") and (r.cmstate = midle) then
369 -- if BUS16 then
370 -- v.address(16 downto 2) := '0' & ba & raddr(11 downto 0); --since 1 bit lower row => tot adress field 14 bits
371 -- else
372 v.address(16 downto 2) := ba & raddr; -- ba(16-15) & raddr(14-2) (2+13= 15 bits)
373 -- end if;
374 v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1;
375 v.startsd := '0';
376 elsif (r.idlecnt = "0000") and (r.cfg.command = "000")
377 and (r.cmstate = midle) and (r.cfg.mobileen(1) = '1') then
378 case r.cfg.pmode is
379 when PM_SR =>
380 v.cfg.cke := '0'; v.sdstate := sref;
381 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
382 v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc; -- Control minimum duration of Self Refresh mode (= tRAS)
383 when PM_PD => v.cfg.cke := '0'; v.sdstate := pd;
384 when PM_DPD =>
385 v.cfg.cke := '0'; v.sdstate := dpd;
386 v.sdcsn := (others => '0'); v.sdwen := '0'; v.rasn := '1'; v.casn := '1';
387 when others =>
388 end case;
389 end if;
390
391 when act1 =>
392 v.rasn := '1'; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
393 if r.cfg.casdel = '1' then v.sdstate := act2; else
394 v.sdstate := act3;
395 if not BUS16 then -- needs if, otherwise it might clock in incorrect write data to state act3_16
396 v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
397 end if;
398 end if;
399 if WPROTEN then
400 v.wprothit := sdi.wprot;
401 if sdi.wprot = '1' then v.hresp := HRESP_ERROR; end if;
402 end if;
403
404 when act2 =>
405 v.sdstate := act3;
406 if not BUS16 then
407 v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1);
408 end if;
409 if WPROTEN and (r.wprothit = '1') then
410 v.hresp := HRESP_ERROR; v.hready := '0';
411 end if;
412
413 when act3 =>
414 v.casn := '0';
415 if BUS16 then --HW adress needed to memory
416 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 1); --only allowed to use tot adressbits - ba bits
417 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 1); --only allowed to use tot adressbits - ba bits
418 v.lhw := r.haddr(1); -- 14-2 = 12 colummn bits => 13 downto 2
419 else
420 v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
421 end if;
422 v.dqm := dqm; v.burst := r.hready; -- ??
423
424 if r.hwrite = '1' then
425
426 if BUS16 then --16 bit
427 if r.size(1) = '1' then --word
428 v.hready := ahbsi.htrans(0) and ahbsi.htrans(1); --delayed this check 1 state to keep write data correct in act3_16
429 v.burst := ahbsi.htrans(0) and ahbsi.htrans(1);
430 v.sdstate := act3_16; -- goto state for second part of word transfer
431 -- v.lhw := '0'; --write MSB 16 bits to AMBA adress that ends with 00
432 else --halfword or byte
433 v.sdstate := act3_16; v.hready := '1';
434 end if;
435 else --32 bit or 64
436 v.sdstate := wr1;
437 if ahbsi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if;
438 end if;
439 v.sdwen := '0'; v.bdrive := '0'; --write
440 if WPROTEN and (r.wprothit = '1') then
441 v.hresp := HRESP_ERROR; v.hready := '1';
442 if BUS16 then v.sdstate := act3_16; else v.sdstate := wr1; end if;
443 v.sdwen := '1'; v.bdrive := '1'; v.casn := '1'; --skip write, remember hready high in next state
444 end if;
445 else v.sdstate := rd1; end if;
446
447 when act3_16 => --handle 16 bit and WORD write
448 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 2) & '1';
449 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 2) & '1';
450 v.lhw := '1';
451 if (r.hready and r.burst) = '1' and not (WPROTEN and (r.wprothit = '1')) then
452 v.hready := '0'; --kolla på transfertyp nonseq om vi vill delaya nedankoll.
453 if( ahbsi.htrans = "11" and
454 not ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) and
455 not ((r.haddr(9) xor ahbsi.haddr(9)) = '1' and r.cfg.csize = "00") ) then
456 v.sdstate := wr1_16;
457 end if;
458 elsif r.burst = '1' or (r.hready and not r.burst) = '1' then --terminate burst or single write
459 v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
460 v.dqm := (others => '1');
461 else -- complete single write
462 v.hready := '1';
463 v.sdstate := act3_16; --gick till wr1 förut
464 end if;
465
466 when wr1_16 =>
467 v.address(14 downto 2) := r.haddr(12 downto 11) & '0' & r.haddr(10 downto 1);
468 -- v.address(13 downto 2) := r.haddr(11) & '0' & r.haddr(10 downto 1);
469 v.lhw := r.haddr(1);
470 v.sdstate := act3_16;
471 v.hready := '1';
472
473 when wr1 =>
474 v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2);
475 if (((r.burst and r.hready) = '1') and (r.htrans = "11"))
476 and not (WPROTEN and (r.wprothit = '1'))
477 then
478 v.hready := ahbsi.htrans(0) and ahbsi.htrans(1) and r.hready;
479 if ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) then -- exit on refresh
480 v.hready := '0';
481 end if;
482 else
483 v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1';
484 v.dqm := (others => '1');
485 end if;
486
487 when wr2 =>
488 if (r.cfg.trp = '0') then v.rasn := '0'; v.sdwen := '0'; end if;
489 v.sdstate := wr3;
490
491 when wr3 =>
492 if (r.cfg.trp = '1') then
493 v.rasn := '0'; v.sdwen := '0'; v.sdstate := wr4;
494 else
495 v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1'; v.sdstate := sidle;
496 v.idlecnt := (others => '1');
497 end if;
498
499 when wr4 =>
500 v.sdcsn := "11"; v.rasn := '1'; v.sdwen := '1';
501 if (r.cfg.trp = '1') then v.sdstate := wr5;
502 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
503
504 when wr5 =>
505 v.sdstate := sidle; v.idlecnt := (others => '1');
506
507 when rd1 => --first read applied to sdram
508 v.casn := '1'; v.sdstate := rd7; --nop
509 if not BUS16 then --starting adress cannot be XXXX...111 since we have word burst in this case. and lowest bit always 0.
510 if lineburst and (ahbsi.htrans = "11") then
511 if r.haddr(4 downto 2) = "111" then
512 v.address(9 downto 5) := r.address(9 downto 5) + 1; --adds only within 1KB limit.
513 v.address(4 downto 2) := "000"; v.casn := '0';
514 end if;
515 end if;
516 end if;
517
518 when rd7 =>
519 v.casn := '1'; --nop
520 if BUS16 then
521 if r.cfg.casdel = '1' then --casdel3
522 v.sdstate := rd2;
523 if lineburst and (ahbsi.htrans = "11") then
524 if r.haddr(3 downto 1) = "110" then
525 v.address(10 downto 5) := r.address(10 downto 5) + 1;
526 v.address(4 downto 2) := "000"; v.casn := '0';
527 end if;
528 end if;
529 else --casdel2
530 v.sdstate := rd3;
531 if ahbsi.htrans /= "11" then
532 if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if;
533 elsif lineburst then
534 if r.haddr(3 downto 1) = "110" then
535 v.address(10 downto 5) := r.address(10 downto 5) + 1;
536 v.address(4 downto 2) := "000"; v.casn := '0';
537 end if;
538 end if;
539 end if;
540 else -- 32 bit or larger
541 if r.cfg.casdel = '1' then --casdel3
542 v.sdstate := rd2;
543 if lineburst and (ahbsi.htrans = "11") then
544 if r.haddr(4 downto 2) = "110" then
545 v.address(9 downto 5) := r.address(9 downto 5) + 1;
546 v.address(4 downto 2) := "000"; v.casn := '0';
547 end if;
548 end if;
549 else --casdel2
550 v.sdstate := rd3;
551 if ahbsi.htrans /= "11" then
552 if (r.trfc(3 downto 1) = "000") then v.rasn := '0'; v.sdwen := '0'; end if; --precharge
553 elsif lineburst then
554 if r.haddr(4 downto 2) = "110" then
555 v.address(9 downto 5) := r.address(9 downto 5) + 1;
556 v.address(4 downto 2) := "000"; v.casn := '0';
557 end if;
558 end if;
559 end if;
560 end if;
561
562 when rd2 =>
563 v.casn := '1'; v.sdstate := rd3;
564 if BUS16 then
565 if ahbsi.htrans /= "11" then
566 v.rasn := '0'; v.sdwen := '0'; v.dqm := (others => '1'); --precharge & DQM
567 --note that DQM always has 2 cycle delay before blocking data. So NP if we fetch second HW
568 end if;
569 else
570 if ahbsi.htrans /= "11" then v.rasn := '0'; v.sdwen := '0'; v.dqm := (others => '1'); --precharge & DQM
571 elsif lineburst then
572 if r.haddr(4 downto 2) = "101" then
573 v.address(9 downto 5) := r.address(9 downto 5) + 1;
574 v.address(4 downto 2) := "000"; v.casn := '0';
575 end if;
576 end if;
577 end if;
578
579 when rd3 => --first read data from sdram output v.lhw := r.haddr(1);
580 v.casn := '1'; --if read before cas makes nop else if pre => no difference
581 if BUS16 then
582 --note if read is for halfwor or byte we dont want to read a second time but exit.
583 --if the read is a word we need to change LHW to one since the next read should be muxed in next cylcle.
584 -- if r.size(1) = '1' then --word v.hready := not r.size(1)
585 -- v.sdstate := rd4_16; v.hready := '0'; --hready low since just first part of a word
586 -- v.lhw := '1'; -- read low 16 next state
587 -- else --HW or byte
588 -- v.sdstate := rd4_16; v.hready := '1';
589 -- end if;
590 v.sdstate := rd4_16;
591 v.lhw := not r.lhw; --r.lhw is 0 for word, we should invert for next half of word.For HW or Byte v.lhw does not matter.
592 v.hready := not r.size(1); --if word transfer the r.size(1) is 1 and hready goes low.If HW or byte r.size(1)=0 => hready=1
593 if r.sdwen = '0' then
594 v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); -- make DSEL (NOP)
595 elsif lineburst and ((ahbsi.htrans = "11") and (r.cfg.casdel = '1')) then --only enter if cl3
596 if r.haddr(3 downto 1) = "100" then
597 v.address(10 downto 5) := r.address(10 downto 5) + 1;
598 v.address(4 downto 2) := "000"; v.casn := '0';
599 end if;
600 end if;
601 else --32 bit or larger
602 v.sdstate := rd4; v.hready := '1';
603 if r.sdwen = '0' then
604 v.rasn := '1'; v.sdwen := '1'; v.sdcsn := "11"; v.dqm := (others => '1'); -- make DSEL (NOP)
605 elsif lineburst and (ahbsi.htrans = "11") and (r.casn = '1') then
606 if r.haddr(4 downto 2) = ("10" & not r.cfg.casdel) then
607 v.address(9 downto 5) := r.address(9 downto 5) + 1;
608 v.address(4 downto 2) := "000"; v.casn := '0';
609 end if;
610 end if;
611 end if;
612
613 when rd4_16 => --enter as word (r.hready is still 0) else 1. If hready one next transfer sampled into v.
614 --v.hready := '1';
615 v.hready := not r.hready;-- if Byte or HW exit with hready low. If word flip bit, makes correct exit with hready low.
616 v.lhw := not r.lhw; --r.lhw is one the first time we enter (taking care of second part of word)
617 v.casn := '1';
618 --quit on: Single transfer CL 2/3 (prcharge if CL 2 and timer was not 0)
619 if (ahbsi.htrans /= "11" and (r.hready = '1')) or
620 ((r.haddr(9) xor ahbsi.haddr(9)) = '1' and r.cfg.csize = "00" and r.hready = '1') or --probably dont have to check hready 1 since if 0 adresses equal.
621 ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100") and (r.hready = '1')) then --quit on: ST W/HW/BYTE OR
622 --v.hready := '0'; --if Byte or HW exit with hready low, if ST word exit with high.
623 v.dqm := (others => '1');
624 if r.sdcsn /= "11" then --not prechargeing
625 v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5; --precharge
626 else--exit
627 if r.cfg.trp = '1' then v.sdstate := rd6;
628 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
629 end if;
630 elsif lineburst then --NOTE: r.casn = 1 makes sure its the first halfword of a word that is checked (hready low)
631 if r.cfg.casdel = '0' then
632 if (r.haddr(3 downto 1) = "100") and (r.casn = '1') then --lline = 011 if casdel =1, 100 if casdel= 0
633 v.address(10 downto 5) := r.address(10 downto 5) + 1;
634 v.address(4 downto 2) := "000"; v.casn := '0';
635 end if;
636 else
637 if (r.haddr(3 downto 1) = "010") and (r.hready = '1') then --lline = 011 if casdel =1, 100 if casdel= 0
638 v.address(10 downto 5) := r.address(10 downto 5) + 1;
639 v.address(4 downto 2) := "000"; v.casn := '0';
640 end if;
641 end if;
642 end if;
643
644 when rd4 =>
645 v.hready := '1'; v.casn := '1';
646 if (ahbsi.htrans /= "11") or (r.sdcsn = "11") or
647 ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "100")) -- exit on refresh
648 then
649 v.hready := '0'; v.dqm := (others => '1');
650 if (r.sdcsn /= "11") then
651 v.rasn := '0'; v.sdwen := '0'; v.sdstate := rd5;
652 else
653 if r.cfg.trp = '1' then v.sdstate := rd6;
654 else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
655 end if;
656 elsif lineburst then
657 if (r.haddr(4 downto 2) = lline) and (r.casn = '1') then
658 v.address(9 downto 5) := r.address(9 downto 5) + 1;
659 v.address(4 downto 2) := "000"; v.casn := '0';
660 end if;
661 end if;
662
663 when rd5 =>
664 if r.cfg.trp = '1' then v.sdstate := rd6; else v.sdstate := sidle; v.idlecnt := (others => '1'); end if;
665 v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1'; v.dqm := (others => '1');
666 v.casn := '1';
667
668 when rd6 =>
669 v.sdstate := sidle; v.idlecnt := (others => '1'); v.dqm := (others => '1');
670 v.sdcsn := (others => '1'); v.rasn := '1'; v.sdwen := '1';
671
672 when sref =>
673 if (startsd = '1' and (r.hio = '0'))
674 or (r.cfg.command /= "000") or r.cfg.pmode /= PM_SR then
675 if r.trfc = "0000" then -- Minimum duration (= tRAS)
676 v.cfg.cke := '1';
677 v.sdcsn := (others => '0'); v.rasn := '1'; v.casn := '1';
678 end if;
679 if r.cfg.cke = '1' then
680 if (r.idlecnt = "0000") then -- tXSR ns with NOP
681 v.sdstate := sidle;
682 v.idlecnt := (others => '1');
683 v.sref_tmpcom := r.cfg.command;
684 v.cfg.command := "100";
685 end if;
686 else
687 v.idlecnt := r.cfg.txsr;
688 end if;
689 end if;
690
691 when pd =>
692 if (startsd = '1' and (r.hio = '0'))
693 or (r.cfg.command /= "000") or r.cfg.pmode /= PM_PD then
694 v.cfg.cke := '1';
695 v.sdstate := sidle;
696 v.idlecnt := (others => '1');
697 end if;
698
699 when dpd =>
700 v.sdcsn := (others => '1'); v.sdwen := '1'; v.rasn := '1'; v.casn := '1';
701 v.cfg.renable := '0';
702 if (startsd = '1' and r.hio = '0') then
703 v.hready := '1'; -- ack all accesses with Error response
704 v.startsd := '0';
705 v.hresp := HRESP_ERROR;
706 elsif r.cfg.pmode /= PM_DPD then
707 v.cfg.cke := '1';
708 if r.cfg.cke = '1' then
709 v.sdstate := sidle;
710 v.idlecnt := (others => '1');
711 v.cfg.renable := '1';
712 end if;
713 end if;
714
715 when others =>
716 v.sdstate := sidle; v.idlecnt := (others => '1');
717 end case;
718
719 -- sdram commands
720
721 case r.cmstate is
722 when midle =>
723 if r.sdstate = sidle then
724 case r.cfg.command is
725 when "010" => -- precharge
726 v.sdcsn := (others => '0'); v.rasn := '0'; v.sdwen := '0';
727 v.address(12) := '1'; v.cmstate := active;
728 when "100" => -- auto-refresh
729 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
730 v.cmstate := active;
731 when "110" => -- Lodad Mode Reg
732 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
733 v.sdwen := '0'; v.cmstate := active;
734 if lineburst then
735 v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0011";
736 else
737 v.address(16 downto 2) := "0000010001" & r.cfg.casdel & "0111";
738 end if;
739 when "111" => -- Load Ext-Mode Reg
740 v.sdcsn := (others => '0'); v.rasn := '0'; v.casn := '0';
741 v.sdwen := '0'; v.cmstate := active;
742 v.address(16 downto 2) := "10000000" & r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0)
743 & r.cfg.pasr(2 downto 0);
744 when others => null;
745 end case;
746 end if;
747 when active =>
748 v.sdcsn := (others => '1'); v.rasn := '1'; v.casn := '1';
749 v.sdwen := '1'; --v.cfg.command := "000";
750 v.cfg.command := r.sref_tmpcom; v.sref_tmpcom := "000";
751 v.cmstate := leadout; v.trfc := (r.cfg.trp and r.cfg.mobileen(1)) & r.cfg.trfc;
752 when leadout =>
753 if r.trfc = "0000" then v.cmstate := midle; end if;
754
755 end case;
756
757 -- sdram init
758
759 case r.istate is
760 when iidle =>
761 v.cfg.cke := '1';
762 if r.cfg.renable = '1' and r.cfg.cke = '1' then
763 v.cfg.command := "010"; v.istate := pre;
764 end if;
765 when pre =>
766 if r.cfg.command = "000" then
767 v.cfg.command := "100"; v.istate := ref; v.icnt := "111";
768 end if;
769 when ref =>
770 if r.cfg.command = "000" then
771 v.cfg.command := "100"; v.icnt := r.icnt - 1;
772 if r.icnt = "000" then v.istate := lmode; v.cfg.command := "110"; end if;
773 end if;
774 when lmode =>
775 if r.cfg.command = "000" then
776 if r.cfg.mobileen = "11" then
777 v.cfg.command := "111"; v.istate := emode;
778 else
779 v.istate := finish;
780 end if;
781 end if;
782 when emode =>
783 if r.cfg.command = "000" then
784 v.istate := finish;
785 end if;
786 when others =>
787 if r.cfg.renable = '0' and r.sdstate /= dpd then
788 v.istate := iidle;
789 end if;
790 end case;
791
792 if (ahbsi.hready and ahbsi.hsel(hindex) ) = '1' then
793 if ahbsi.htrans(1) = '0' then v.hready := '1'; end if;
794 end if;
795
796 if (r.hsel and r.hio and not r.hready) = '1' then v.hready := '1'; end if;
797
798 -- second part of main fsm
799
800 case r.mstate is
801 when active =>
802 if v.hready = '1' then
803 v.mstate := midle;
804 end if;
805 when others => null;
806 end case;
807
808 -- sdram refresh counter
809
810 -- pragma translate_off
811 if not is_x(r.cfg.refresh) then
812 -- pragma translate_on
813 if (r.cfg.renable = '1') and (r.istate = finish) and r.sdstate /= sref then
814 v.refresh := r.refresh - 1;
815 if (v.refresh(14) and not r.refresh(14)) = '1' then
816 v.refresh := r.cfg.refresh;
817 v.cfg.command := "100";
818 arefresh := '1';
819 end if;
820 end if;
821 -- pragma translate_off
822 end if;
823 -- pragma translate_on
824
825 -- AHB register access
826 -- if writing to IO space config regs. Just mapping write data to all config values in config reg
827 if (r.hsel and r.hio and r.hwrite and r.htrans(1)) = '1' then
828 if r.haddr(3 downto 2) = "00" then
829 if pageburst = 2 then v.cfg.pageburst := hwdata(17); end if;
830 v.cfg.command := hwdata(20 downto 18);
831 v.cfg.csize := hwdata(22 downto 21);
832 v.cfg.bsize := hwdata(25 downto 23);
833 v.cfg.casdel := hwdata(26);
834 v.cfg.trfc := hwdata(29 downto 27);
835 v.cfg.trp := hwdata(30);
836 v.cfg.renable := hwdata(31);
837 v.cfg.refresh := hwdata(14 downto 0);
838 v.refresh := (others => '0');
839 elsif r.haddr(3 downto 2) = "01" then
840 if r.cfg.mobileen(1) = '1' and mobile /= 3 then v.cfg.mobileen(0) := hwdata(31); end if;
841 if r.cfg.pmode = "000" then
842 v.cfg.cke := hwdata(30);
843 end if;
844 if r.cfg.mobileen(1) = '1' then
845 v.cfg.txsr := hwdata(23 downto 20);
846 v.cfg.pmode := hwdata(18 downto 16);
847 v.cfg.ds(3 downto 2) := hwdata( 6 downto 5);
848 v.cfg.tcsr(3 downto 2) := hwdata( 4 downto 3);
849 v.cfg.pasr(5 downto 3) := hwdata( 2 downto 0);
850 end if;
851 end if;
852 end if;
853
854 -- Disable CS and DPD when Mobile SDR is Disabled
855 if r.cfg.mobileen(0) = '0' then v.cfg.pmode(2) := '0'; end if;
856
857 -- Update EMR when ds, tcsr or pasr change
858 if r.cfg.command = "000" and arefresh = '0' and r.cfg.mobileen(0) = '1' then
859 if r.cfg.ds(1 downto 0) /= r.cfg.ds(3 downto 2) then
860 v.cfg.command := "111"; v.cfg.ds(1 downto 0) := r.cfg.ds(3 downto 2);
861 end if;
862 if r.cfg.tcsr(1 downto 0) /= r.cfg.tcsr(3 downto 2) then
863 v.cfg.command := "111"; v.cfg.tcsr(1 downto 0) := r.cfg.tcsr(3 downto 2);
864 end if;
865 if r.cfg.pasr(2 downto 0) /= r.cfg.pasr(5 downto 3) then
866 v.cfg.command := "111"; v.cfg.pasr(2 downto 0) := r.cfg.pasr(5 downto 3);
867 end if;
868 end if;
869
870 regsd := (others => '0');
871 --reads out config registers (r/w does not matter) according to manual depending on address, notice generic determines data width.
872 if r.haddr(3 downto 2) = "00" then
873 regsd(31 downto 18) := r.cfg.renable & r.cfg.trp & r.cfg.trfc &
874 r.cfg.casdel & r.cfg.bsize & r.cfg.csize & r.cfg.command;
875 if not lineburst then regsd(17) := '1'; end if;
876 regsd(16) := r.cfg.mobileen(1);
877 if BUS64 then regsd(15) := '1'; end if;
878 regsd(14 downto 0) := r.cfg.refresh;
879 elsif r.haddr(3 downto 2) = "01" then
880 regsd(31) := r.cfg.mobileen(0);
881 regsd(30) := r.cfg.cke;
882 regsd(23 downto 0) := r.cfg.txsr & '0' & r.cfg.pmode & "000000000" &
883 r.cfg.ds(1 downto 0) & r.cfg.tcsr(1 downto 0) & r.cfg.pasr(2 downto 0);
884 end if;
885
886 if (r.hsel and r.hio) = '1' then dout := regsd;
887 else
888 if BUS64 and r.bsel = '1' then dout := r.hrdata(63 downto 32);
889 else dout := r.hrdata(31 downto 0); end if;
890 end if;
891
892 v.nbdrive := not v.bdrive;
893
894 if oepol = 1 then bdrive := r.nbdrive; vbdrive := (others => v.nbdrive);
895 else bdrive := r.bdrive; vbdrive := (others => v.bdrive);end if;
896
897 -- reset
898
899 if rst = '0' then
900 v.sdstate := sidle;
901 v.mstate := midle;
902 v.istate := iidle;
903 v.cmstate := midle;
904 v.hsel := '0';
905 v.cfg.command := "000";
906 v.cfg.csize := "01";
907 v.cfg.bsize := "011";
908 v.cfg.casdel := '1';
909 v.cfg.trfc := "111";
910 if pwron = 1 then v.cfg.renable := '1';
911 else v.cfg.renable := '0'; end if;
912 v.cfg.trp := '1';
913 v.dqm := (others => '1');
914 v.sdwen := '1';
915 v.rasn := '1';
916 v.casn := '1';
917 v.hready := '1';
918 v.bsel := '0';
919 v.startsd := '0';
920 if (pageburst = 2) then
921 v.cfg.pageburst := '0';
922 end if;
923 if mobile >= 2 then v.cfg.mobileen := "11";
924 elsif mobile = 1 then v.cfg.mobileen := "10";
925 else v.cfg.mobileen := "00"; end if;
926 v.cfg.txsr := (others => '1');
927 v.cfg.pmode := (others => '0');
928 v.cfg.ds := (others => '0');
929 v.cfg.tcsr := (others => '0');
930 v.cfg.pasr := (others => '0');
931 if mobile >= 2 then v.cfg.cke := '0';
932 else v.cfg.cke := '1'; end if;
933 v.sref_tmpcom := "000";
934 v.idlecnt := (others => '1');
935 end if;
936
937 ri <= v;
938 ribdrive <= vbdrive;
939
940 ahbso.hready <= r.hready;
941 ahbso.hresp <= r.hresp;
942 ahbso.hrdata <= ahbdrivedata(dout);
943
944 end process;
945
946 --sdo.sdcke <= (others => '1');
947 sdo.sdcke <= (others => r.cfg.cke);
948 ahbso.hconfig <= hconfig;
949 ahbso.hirq <= (others => '0');
950 ahbso.hindex <= hindex;
951 ahbso.hsplit <= (others => '0');
952
953 -- Quick hack to get rid of undriven signal warnings. Check this for future
954 -- merge with main sdctrl.
955 drivehack : block
956 begin
957 sdo.qdrive <= '0';
958 sdo.nbdrive <= '0';
959 sdo.ce <= '0';
960 sdo.moben <= '0';
961 sdo.cal_rst <= '0';
962 sdo.oct <= '0';
963 sdo.xsdcsn <= (others => '1');
964 sdo.data(127 downto 16) <= (others => '0');
965 sdo.cb <= (others => '0');
966 sdo.ba <= (others => '0');
967 sdo.sdck <= (others => '0');
968 sdo.cal_en <= (others => '0');
969 sdo.cal_inc <= (others => '0');
970 sdo.cal_pll <= (others => '0');
971 sdo.odt <= (others => '0');
972 sdo.conf <= (others => '0');
973 sdo.vcbdrive <= (others => '0');
974 sdo.dqs_gate <= '0';
975 sdo.cbdqm <= (others => '0');
976 sdo.cbcal_en <= (others => '0');
977 sdo.cbcal_inc <= (others => '0');
978 sdo.read_pend <= (others => '0');
979 sdo.regwdata <= (others => '0');
980 sdo.regwrite <= (others => '0');
981 end block drivehack;
982
983 regs : process(clk, rst) begin
984 if rising_edge(clk) then
985 r <= ri; rbdrive <= ribdrive;
986 if rst = '0' then r.icnt <= (others => '0'); end if;
987 end if;
988 if (rst = '0') then
989 r.sdcsn <= (others => '1'); r.bdrive <= '1'; r.nbdrive <= '0';
990 if oepol = 0 then rbdrive <= (others => '1');
991 else rbdrive <= (others => '0'); end if;
992 end if;
993 end process;
994
995 rgen : if not SDINVCLK generate
996 sdo.address <= r.address;
997 sdo.bdrive <= r.nbdrive when oepol = 1 else r.bdrive;
998 sdo.vbdrive <= zero32 & rbdrive;
999 sdo.sdcsn <= r.sdcsn;
1000 sdo.sdwen <= r.sdwen;
1001 sdo.dqm <= "11111111" & r.dqm;
1002 sdo.rasn <= r.rasn;
1003 sdo.casn <= r.casn;
1004
1005 mux16_wrdata : if BUS16 generate --mux data depending on Low/High HW
1006 sdo.data(15 downto 0) <= r.hwdata(15 downto 0) when r.lhw = '1' else r.hwdata(31 downto 16);
1007 end generate;
1008
1009 wrdata : if not BUS16 generate
1010 drivebus: for i in 0 to sdbits/64 generate
1011 sdo.data(31+32*i downto 32*i) <= r.hwdata;
1012 end generate;
1013 end generate;
1014 end generate;
1015
1016 ngen : if SDINVCLK generate
1017 nregs : process(clk, rst) begin
1018 if falling_edge(clk) then
1019 sdo.address <= r.address;
1020 if oepol = 1 then sdo.bdrive <= r.nbdrive;
1021 else sdo.bdrive <= r.bdrive; end if;
1022 sdo.vbdrive <= zero32 & rbdrive;
1023 sdo.sdcsn <= r.sdcsn;
1024 sdo.sdwen <= r.sdwen;
1025 sdo.dqm <= "11111111" & r.dqm;
1026 sdo.rasn <= r.rasn;
1027 sdo.casn <= r.casn;
1028 if BUS16 then --mux data depending on Low/High HW
1029 if (r.lhw ='1') then
1030 sdo.data(15 downto 0) <= r.hwdata(15 downto 0);
1031 else
1032 sdo.data(15 downto 0) <= r.hwdata(31 downto 16);
1033 end if;
1034 end if;
1035
1036 if not BUS16 then
1037 for i in 0 to sdbits/64 loop
1038 sdo.data(31+32*i downto 32*i) <= r.hwdata;
1039 end loop;
1040 end if;
1041 end if;
1042 if rst = '0' then sdo.sdcsn <= (others => '1'); end if;
1043 end process;
1044 end generate;
1045
1046 -- pragma translate_off
1047 bootmsg : report_version
1048 generic map ("sdctrl16" & tost(hindex) &
1049 ": PC133 SDRAM controller rev " & tost(REVISION));
1050 -- pragma translate_on
1051
1052 end;
1053
@@ -0,0 +1,200
1 ------------------------------------------------------------------------------
2 -- LEON3 Demonstration design test bench
3 -- Copyright (C) 2004 Jiri Gaisler, Gaisler Research
4 ------------------------------------------------------------------------------
5 ------------------------------------------------------------------------------
6 -- This file is a part of the GRLIB VHDL IP LIBRARY
7 -- Copyright (C) 2003 - 2008, Gaisler Research
8 -- Copyright (C) 2008 - 2014, Aeroflex Gaisler
9 -- Copyright (C) 2015 - 2016, Cobham Gaisler
10 --
11 -- This program is free software; you can redistribute it and/or modify
12 -- it under the terms of the GNU General Public License as published by
13 -- the Free Software Foundation; either version 2 of the License, or
14 -- (at your option) any later version.
15 --
16 -- This program is distributed in the hope that it will be useful,
17 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
18 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 -- GNU General Public License for more details.
20 --
21 -- You should have received a copy of the GNU General Public License
22 -- along with this program; if not, write to the Free Software
23 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25 library ieee;
26 use ieee.std_logic_1164.all;
27 library gaisler;
28 use gaisler.libdcom.all;
29 use gaisler.sim.all;
30 use work.debug.all;
31 library techmap;
32 use techmap.gencomp.all;
33 library micron;
34 use micron.components.all;
35 library grlib;
36 use grlib.stdlib.all;
37
38 use work.config.all; -- configuration
39
40
41 entity testbench is
42 generic (
43 fabtech : integer := CFG_FABTECH;
44 memtech : integer := CFG_MEMTECH;
45 padtech : integer := CFG_PADTECH;
46 clktech : integer := CFG_CLKTECH;
47 disas : integer := CFG_DISAS; -- Enable disassembly to console
48 dbguart : integer := CFG_DUART; -- Print UART on console
49 pclow : integer := CFG_PCLOW;
50
51 clkperiod : integer := 20; -- system clock period
52 romdepth : integer := 22 -- rom address depth (flash 4 MB)
53 -- sramwidth : integer := 32; -- ram data width (8/16/32)
54 -- sramdepth : integer := 20; -- ram address depth
55 -- srambanks : integer := 2 -- number of ram banks
56 );
57 end;
58
59 architecture behav of testbench is
60
61 constant promfile : string := "prom.srec"; -- rom contents
62 constant sramfile : string := "ram.srec"; -- ram contents
63 constant sdramfile : string := "ram.srec"; -- sdram contents
64
65
66 signal SW : std_logic_vector(4 downto 1);
67 signal clk : std_logic := '0';
68 signal Rst : std_logic := '0'; -- Reset
69 constant ct : integer := clkperiod/2;
70
71 signal address : std_logic_vector(21 downto 0);
72 signal data : std_logic_vector(31 downto 24);
73
74 signal romsn : std_logic;
75 signal oen : std_logic;
76 signal writen : std_logic;
77 signal dsuen, dsutx, dsurx, dsubre, dsuact : std_logic;
78 signal dsurst : std_logic;
79 signal error : std_logic;
80
81 signal sdcke : std_logic;
82 signal sdcsn : std_logic;
83 signal sdwen : std_logic; -- write en
84 signal sdrasn : std_logic; -- row addr stb
85 signal sdcasn : std_logic; -- col addr stb
86 signal dram_ldqm : std_logic;
87 signal dram_udqm : std_logic;
88 signal sdclk : std_logic;
89 signal dram_ba : std_logic_vector(1 downto 0);
90
91
92
93 constant lresp : boolean := false;
94
95
96 signal sa : std_logic_vector(12 downto 0);
97 signal sd : std_logic_vector(15 downto 0);
98
99
100 begin
101
102 clk <= not clk after ct * 1 ns; --50 MHz clk
103 rst <= dsurst; --reset
104 dsuen <= '1';
105 dsubre <= '1'; -- inverted on the board
106 sw(1) <= rst;
107
108 d3 : entity work.leon3mp
109 generic map ( fabtech, memtech, padtech, clktech, disas, dbguart, pclow )
110 port map (
111 CLK50 => clk,
112 LEDS => open,
113 SW => SW,
114 dram_addr => sa,
115 dram_ba_0 => dram_ba(0),
116 dram_ba_1 => dram_ba(1),
117 dram_dq => sd(15 downto 0),
118 dram_clk => sdclk,
119 dram_cke => sdcke,
120 dram_cs_n => sdcsn,
121 dram_we_n => sdwen,
122 dram_ras_n => sdrasn,
123 dram_cas_n => sdcasn,
124 dram_ldqm => dram_ldqm,
125 dram_udqm => dram_udqm,
126 uart_txd => dsutx,
127 uart_rxd => dsurx);
128
129 u1: entity work.mt48lc16m16a2 generic map (addr_bits => 13, col_bits => 9, index => 1024, fname => sdramfile)
130 PORT MAP(
131 Dq => sd(15 downto 0), Addr => sa(12 downto 0),
132 Ba => dram_ba, Clk => sdclk, Cke => sdcke,
133 Cs_n => sdcsn, Ras_n => sdrasn, Cas_n => sdcasn, We_n => sdwen,
134 Dqm(0) => dram_ldqm, Dqm(1) => dram_udqm );
135
136
137
138 error <= 'H'; -- ERROR pull-up
139
140 iuerr : process
141 begin
142 wait for 2500 ns;
143 if to_x01(error) = '1' then wait on error; end if;
144 assert (to_x01(error) = '1')
145 report "*** IU in error mode, simulation halted ***"
146 severity failure ;
147 end process;
148
149 data <= buskeep(data) after 5 ns;
150 sd <= buskeep(sd) after 5 ns;
151
152 dsucom : process
153 variable w32 : std_logic_vector(31 downto 0);
154 constant txp : time := 160 * 1 ns;
155 procedure writeReg(signal dsutx : out std_logic; address : integer; value : integer) is
156 begin
157 txc(dsutx, 16#c0#, txp); --control byte
158 txa(dsutx, (address / (256*256*256)) , (address / (256*256)), (address / (256)), address, txp); --adress
159 txa(dsutx, (value / (256*256*256)) , (value / (256*256)), (value / (256)), value, txp); --write data
160 end;
161
162 procedure readReg(signal dsurx : in std_logic; signal dsutx : out std_logic; address : integer; value: out std_logic_vector) is
163
164 begin
165 txc(dsutx, 16#a0#, txp); --control byte
166 txa(dsutx, (address / (256*256*256)) , (address / (256*256)), (address / (256)), address, txp); --adress
167 rxi(dsurx, value, txp, lresp); --write data
168 end;
169
170 procedure dsucfg(signal dsurx : in std_logic; signal dsutx : out std_logic) is
171 variable c8 : std_logic_vector(7 downto 0);
172 begin
173 dsutx <= '1';
174 dsurst <= '0'; --reset low
175 wait for 500 ns;
176 dsurst <= '1'; --reset high
177 --wait; --evig w8
178 wait for 5000 ns;
179 txc(dsutx, 16#55#, txp);
180 --dsucfg(dsutx, dsurx);
181 writeReg(dsutx,16#40000000#,16#12345678#);
182 writeReg(dsutx,16#40000004#,16#22222222#);
183 writeReg(dsutx,16#40000008#,16#33333333#);
184 writeReg(dsutx,16#4000000C#,16#44444444#);
185
186 readReg(dsurx,dsutx,16#40000000#,w32);
187 readReg(dsurx,dsutx,16#40000004#,w32);
188 readReg(dsurx,dsutx,16#40000008#,w32);
189 readReg(dsurx,dsutx,16#4000000C#,w32);
190
191 end;
192
193 begin
194 dsucfg(dsutx, dsurx);
195
196
197 wait;
198 end process;
199 end ;
200
@@ -0,0 +1,143
1 # Clocks
2 NET "CLK50" PERIOD = 20 ns |LOC = "K3";
3 #NET "CLK32" PERIOD = 31.25 ns | LOC = "J4";
4 # LEDs
5 NET "LEDS<0>" LOC="P11" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
6 NET "LEDS<1>" LOC="N9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
7 NET "LEDS<2>" LOC="M9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
8 NET "LEDS<3>" LOC="P9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
9 NET "LEDS<4>" LOC="T8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
10 NET "LEDS<5>" LOC="N8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
11 NET "LEDS<6>" LOC="P8" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
12 NET "LEDS<7>" LOC="P7" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
13
14 # DIP Switches
15 NET "SW<1>" LOC="L1" |IOSTANDARD=LVTTL |PULLUP;
16 NET "SW<2>" LOC="L3" |IOSTANDARD=LVTTL |PULLUP;
17 NET "SW<3>" LOC="L4" |IOSTANDARD=LVTTL |PULLUP;
18 NET "SW<4>" LOC="L5" |IOSTANDARD=LVTTL |PULLUP;
19
20 NET "uart_rxd" LOC="M7" |IOSTANDARD=LVTTL;
21 NET "uart_txd" LOC="N6" |IOSTANDARD=LVTTL;
22
23 # SDRAM
24 NET "dram_udqm" LOC="F15" |IOSTANDARD=LVTTL;
25 NET "dram_clk" LOC="G16" |IOSTANDARD=LVTTL;
26 NET "dram_cke" LOC="H16" |IOSTANDARD=LVTTL;
27 NET "dram_ba_1" LOC="T14" |IOSTANDARD=LVTTL;
28 NET "dram_ba_0" LOC="R14" |IOSTANDARD=LVTTL;
29 NET "dram_cs_n" LOC="R1" |IOSTANDARD=LVTTL;
30 NET "dram_ras_n" LOC="R2" |IOSTANDARD=LVTTL;
31 NET "dram_cas_n" LOC="T4" |IOSTANDARD=LVTTL;
32 NET "dram_we_n" LOC="R5" |IOSTANDARD=LVTTL;
33 NET "dram_ldqm" LOC="T5" |IOSTANDARD=LVTTL;
34 NET "dram_addr<0>" LOC="T15" |IOSTANDARD=LVTTL;
35 NET "dram_addr<1>" LOC="R16" |IOSTANDARD=LVTTL;
36 NET "dram_addr<2>" LOC="P15" |IOSTANDARD=LVTTL;
37 NET "dram_addr<3>" LOC="P16" |IOSTANDARD=LVTTL;
38 NET "dram_addr<4>" LOC="N16" |IOSTANDARD=LVTTL;
39 NET "dram_addr<5>" LOC="M15" |IOSTANDARD=LVTTL;
40 NET "dram_addr<6>" LOC="M16" |IOSTANDARD=LVTTL;
41 NET "dram_addr<7>" LOC="L16" |IOSTANDARD=LVTTL;
42 NET "dram_addr<8>" LOC="K15" |IOSTANDARD=LVTTL;
43 NET "dram_addr<9>" LOC="K16" |IOSTANDARD=LVTTL;
44 NET "dram_addr<10>" LOC="R15" |IOSTANDARD=LVTTL;
45 NET "dram_addr<11>" LOC="J16" |IOSTANDARD=LVTTL;
46 NET "dram_addr<12>" LOC="H15" |IOSTANDARD=LVTTL;
47 NET "dram_dq<0>" LOC="T13" |IOSTANDARD=LVTTL;
48 NET "dram_dq<1>" LOC="T12" |IOSTANDARD=LVTTL;
49 NET "dram_dq<2>" LOC="R12" |IOSTANDARD=LVTTL;
50 NET "dram_dq<3>" LOC="T9" |IOSTANDARD=LVTTL;
51 NET "dram_dq<4>" LOC="R9" |IOSTANDARD=LVTTL;
52 NET "dram_dq<5>" LOC="T7" |IOSTANDARD=LVTTL;
53 NET "dram_dq<6>" LOC="R7" |IOSTANDARD=LVTTL;
54 NET "dram_dq<7>" LOC="T6" |IOSTANDARD=LVTTL;
55 NET "dram_dq<8>" LOC="F16" |IOSTANDARD=LVTTL;
56 NET "dram_dq<9>" LOC="E15" |IOSTANDARD=LVTTL;
57 NET "dram_dq<10>" LOC="E16" |IOSTANDARD=LVTTL;
58 NET "dram_dq<11>" LOC="D16" |IOSTANDARD=LVTTL;
59 NET "dram_dq<12>" LOC="B16" |IOSTANDARD=LVTTL;
60 NET "dram_dq<13>" LOC="B15" |IOSTANDARD=LVTTL;
61 NET "dram_dq<14>" LOC="C16" |IOSTANDARD=LVTTL;
62 NET "dram_dq<15>" LOC="C15" |IOSTANDARD=LVTTL;
63 #Created by Constraints Editor (xc6slx25-ftg256-3) - 2016/12/08
64 INST "dram_addr(0)" TNM = dram_addr;
65 INST "dram_addr(1)" TNM = dram_addr;
66 INST "dram_addr(2)" TNM = dram_addr;
67 INST "dram_addr(3)" TNM = dram_addr;
68 INST "dram_addr(4)" TNM = dram_addr;
69 INST "dram_addr(5)" TNM = dram_addr;
70 INST "dram_addr(6)" TNM = dram_addr;
71 INST "dram_addr(7)" TNM = dram_addr;
72 INST "dram_addr(8)" TNM = dram_addr;
73 INST "dram_addr(9)" TNM = dram_addr;
74 INST "dram_addr(10)" TNM = dram_addr;
75 INST "dram_addr(11)" TNM = dram_addr;
76 INST "dram_addr(12)" TNM = dram_addr;
77 INST "dram_addr(0)" TNM = dram_out;
78 INST "dram_addr(1)" TNM = dram_out;
79 INST "dram_addr(2)" TNM = dram_out;
80 INST "dram_addr(3)" TNM = dram_out;
81 INST "dram_addr(4)" TNM = dram_out;
82 INST "dram_addr(5)" TNM = dram_out;
83 INST "dram_addr(6)" TNM = dram_out;
84 INST "dram_addr(7)" TNM = dram_out;
85 INST "dram_addr(8)" TNM = dram_out;
86 INST "dram_addr(9)" TNM = dram_out;
87 INST "dram_addr(10)" TNM = dram_out;
88 INST "dram_addr(11)" TNM = dram_out;
89 INST "dram_addr(12)" TNM = dram_out;
90 INST "dram_ba_0" TNM = dram_out;
91 INST "dram_ba_1" TNM = dram_out;
92 INST "dram_cas_n" TNM = dram_out;
93 INST "dram_cke" TNM = dram_out;
94 #INST "dram_clk" TNM = dram_out;
95 INST "dram_cs_n" TNM = dram_out;
96 INST "dram_dq(0)" TNM = dram_out;
97 INST "dram_dq(1)" TNM = dram_out;
98 INST "dram_dq(2)" TNM = dram_out;
99 INST "dram_dq(3)" TNM = dram_out;
100 INST "dram_dq(4)" TNM = dram_out;
101 INST "dram_dq(5)" TNM = dram_out;
102 INST "dram_dq(6)" TNM = dram_out;
103 INST "dram_dq(7)" TNM = dram_out;
104 INST "dram_dq(8)" TNM = dram_out;
105 INST "dram_dq(9)" TNM = dram_out;
106 INST "dram_dq(10)" TNM = dram_out;
107 INST "dram_dq(11)" TNM = dram_out;
108 INST "dram_dq(12)" TNM = dram_out;
109 INST "dram_dq(13)" TNM = dram_out;
110 INST "dram_dq(14)" TNM = dram_out;
111 INST "dram_dq(15)" TNM = dram_out;
112 INST "dram_ldqm" TNM = dram_out;
113 INST "dram_ras_n" TNM = dram_out;
114 INST "dram_udqm" TNM = dram_out;
115 INST "dram_we_n" TNM = dram_out;
116 TIMEGRP "dram_out" OFFSET = OUT 12 ns AFTER "CLK50";
117 INST "dram_dq(0)" TNM = dram_in;
118 INST "dram_dq(1)" TNM = dram_in;
119 INST "dram_dq(2)" TNM = dram_in;
120 INST "dram_dq(3)" TNM = dram_in;
121 INST "dram_dq(4)" TNM = dram_in;
122 INST "dram_dq(5)" TNM = dram_in;
123 INST "dram_dq(6)" TNM = dram_in;
124 INST "dram_dq(7)" TNM = dram_in;
125 INST "dram_dq(8)" TNM = dram_in;
126 INST "dram_dq(9)" TNM = dram_in;
127 INST "dram_dq(10)" TNM = dram_in;
128 INST "dram_dq(11)" TNM = dram_in;
129 INST "dram_dq(12)" TNM = dram_in;
130 INST "dram_dq(13)" TNM = dram_in;
131 INST "dram_dq(14)" TNM = dram_in;
132 INST "dram_dq(15)" TNM = dram_in;
133 TIMEGRP "dram_in" OFFSET = IN 3 ns BEFORE "CLK50" RISING;
134
135
136 NET "spw_rxdp" LOC = "h2";# | IOSTANDARD = LVDS_33;
137 NET "spw_rxdn" LOC = "h1";# | IOSTANDARD = LVDS_33;
138 NET "spw_rxsp" LOC = "f4";# | IOSTANDARD = LVDS_33;
139 NET "spw_rxsn" LOC = "f3";# | IOSTANDARD = LVDS_33;
140 NET "spw_txdp" LOC = "e2";# | IOSTANDARD = LVTTL;
141 NET "spw_txdn" LOC = "e1";# | IOSTANDARD = LVTTL;
142 NET "spw_txsp" LOC = "g3";# | IOSTANDARD = LVTTL;
143 NET "spw_txsn" LOC = "g1";# | IOSTANDARD = LVTTL;
@@ -0,0 +1,83
1 ------------------------------------------------------------------------------
2 -- This file is a part of the LPP VHDL IP LIBRARY
3 -- Copyright (C) 2016, Laboratory of Plasmas Physic - CNRS
4 --
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 3 of the License, or
8 -- (at your option) any later version.
9 --
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
14 --
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ------------------------------------------------------------------------------
19 -- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@lpp.polytechnique.fr
21 ------------------------------------------------------------------------------
22 library ieee;
23 use ieee.std_logic_1164.all;
24 library grlib;
25 use grlib.amba.all;
26 use grlib.stdlib.all;
27 use grlib.devices.all;
28 library gaisler;
29 use gaisler.libdcom.all;
30 use gaisler.uart.all;
31 library lpp;
32 use lpp.lpp_usb.all;
33 use lpp.lpp_amba.all;
34 use lpp.apb_devices_list.all;
35
36
37 entity ahb_ftdi_fifo is
38 generic (
39 oepol : integer := 0;
40 hindex : integer := 0
41 );
42 port (
43 clk : in std_logic;
44 rstn : in std_logic;
45
46 ahbi : in ahb_mst_in_type;
47 ahbo : out ahb_mst_out_type;
48
49 FTDI_RXF : in std_logic;
50 FTDI_TXE : in std_logic;
51 FTDI_SIWUA : out std_logic;
52 FTDI_WR : out std_logic;
53 FTDI_RD : out std_logic;
54 FTDI_D_in : in std_logic_vector(7 downto 0);
55 FTDI_D_out : out std_logic_vector(7 downto 0);
56 FTDI_D_drive : out std_logic
57 );
58 end ahb_ftdi_fifo;
59
60 architecture beh of ahb_ftdi_fifo is
61
62 constant REVISION : integer := 0;
63
64 signal dmai : ahb_dma_in_type;
65 signal dmao : ahb_dma_out_type;
66 signal duarti : dcom_uart_in_type;
67 signal duarto : dcom_uart_out_type;
68
69 begin
70
71 ahbmst0 : ahbmst
72 generic map (hindex => hindex, venid => VENDOR_LPP, devid => LPP_AHB_FTDI_FIFO)
73 port map (rstn, clk, dmai, dmao, ahbi, ahbo);
74
75 dcom_fifo0 : ftdi_async_fifo generic map (oepol)
76 port map (clk, rstn, duarti, duarto, FTDI_RXF, FTDI_TXE, FTDI_SIWUA,
77 FTDI_WR, FTDI_RD, FTDI_D_in, FTDI_D_out, FTDI_D_drive);
78
79 dcom0 : dcom port map (rstn, clk, dmai, dmao, duarti, duarto, ahbi);
80
81
82 end beh;
83
@@ -0,0 +1,142
1 ------------------------------------------------------------------------------
2 -- This file is a part of the LPP VHDL IP LIBRARY
3 -- Copyright (C) 2016, Laboratory of Plasmas Physic - CNRS
4 --
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 3 of the License, or
8 -- (at your option) any later version.
9 --
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
14 --
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ------------------------------------------------------------------------------
19 -- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@lpp.polytechnique.fr
21 ------------------------------------------------------------------------------
22 library ieee;
23 use ieee.std_logic_1164.all;
24 library grlib;
25 use grlib.stdlib.all;
26 use grlib.devices.all;
27 library gaisler;
28 use gaisler.libdcom.all;
29 use gaisler.uart.all;
30 library lpp;
31 use lpp.lpp_usb.all;
32
33
34 entity ftdi_async_fifo is
35 generic (
36 oepol : integer := 0
37 );
38 port (
39 clk : in std_logic;
40 rstn : in std_logic;
41
42 dcom_in : in dcom_uart_in_type;
43 dcom_out : out dcom_uart_out_type;
44
45 FTDI_RXF : in std_logic;
46 FTDI_TXE : in std_logic;
47 FTDI_SIWUA : out std_logic;
48 FTDI_WR : out std_logic;
49 FTDI_RD : out std_logic;
50 FTDI_D_in : in std_logic_vector(7 downto 0);
51 FTDI_D_out : out std_logic_vector(7 downto 0);
52 FTDI_D_drive : out std_logic
53 );
54 end ftdi_async_fifo;
55
56 architecture beh of ftdi_async_fifo is
57
58 type fifo_fsm_st is (idle,waitForTXE,preWrite,Write,postWrite,preRead,Read,postRead);
59 signal state : fifo_fsm_st:=idle;
60 signal output_en : std_logic;
61 signal dready : std_logic;
62
63 begin
64
65 acthi: if oepol = 1 generate
66 output_en <= '1';
67 end generate;
68 actlow: if oepol = 0 generate
69 output_en <= '0';
70 end generate;
71
72 dcom_out.dready <= dready;
73 FTDI_SIWUA <= '1';
74
75 process(rstn,clk)
76 begin
77 if rstn = '0' then
78 FTDI_RD <= '1';
79 FTDI_WR <= '1';
80 FTDI_D_drive <= not output_en;
81 dready <= '0';
82 dcom_out.tsempty <= '0';
83 dcom_out.thempty <= '1';
84 dcom_out.lock <= '1';
85 dcom_out.data <= (others => '0');
86 elsif clk'event and clk='1' then
87 case state is
88 when idle =>
89 if dcom_in.read = '1' then
90 dready <= '0';
91 end if;
92 FTDI_D_drive <= not output_en;
93 FTDI_WR <= '1';
94 dcom_out.thempty <= '1';
95 if dcom_in.write = '1' then
96 dcom_out.thempty <= '0';
97 state <= waitForTXE;
98 elsif FTDI_RXF = '0' and dready = '0' then
99 state <= preRead;
100 FTDI_RD <= '0';
101 end if;
102 when waitForTXE =>
103 if FTDI_TXE = '0' then
104 state <= preWrite;
105 FTDI_D_drive <= output_en;
106 FTDI_D_out <= dcom_in.data;
107 end if;
108 when preWrite =>
109 FTDI_WR <= '0';
110 state <= Write;
111 when Write =>
112 FTDI_D_drive <= not output_en;
113 state <= idle;
114 when preRead =>
115 state <= Read;
116 dcom_out.data <= FTDI_D_in;
117 when Read =>
118 FTDI_RD <= '1';
119 dready <= '1';
120 state <= idle;
121 when others => NULL;
122 end case;
123 end if;
124 end process;
125
126 end beh;
127
128 -- type dcom_uart_in_type is record
129 -- read : std_ulogic;
130 -- write : std_ulogic;
131 -- data : std_logic_vector(7 downto 0);
132 -- end record;
133
134 -- type dcom_uart_out_type is record
135 -- dready : std_ulogic; -> data from ftdi to DCOM
136 -- tsempty : std_ulogic; -> not used by decom -> set to 0
137 -- thempty : std_ulogic; -> tels dcom that ready to write to ftdi
138 -- lock : std_ulogic; -> set to 1
139 -- enable : std_ulogic; -> unused
140 -- data : std_logic_vector(7 downto 0);
141 -- end record;
142
@@ -0,0 +1,132
1 ------------------------------------------------------------------------------
2 -- This file is a part of the LPP VHDL IP LIBRARY
3 -- Copyright (C) 2016, Laboratory of Plasmas Physic - CNRS
4 --
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 3 of the License, or
8 -- (at your option) any later version.
9 --
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
14 --
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ------------------------------------------------------------------------------
19 -- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@lpp.polytechnique.fr
21 ------------------------------------------------------------------------------
22 library ieee;
23 use ieee.std_logic_1164.all;
24 library grlib;
25 use grlib.stdlib.all;
26 use grlib.devices.all;
27 library gaisler;
28 use gaisler.libdcom.all;
29 use gaisler.uart.all;
30 library lpp;
31 use lpp.lpp_usb.all;
32
33
34 entity ftdi_async_fifo_loopback is
35 generic (
36 oepol : integer := 0
37 );
38 port (
39 clk : in std_logic;
40 rstn : in std_logic;
41
42
43 FTDI_RXF : in std_logic;
44 FTDI_TXE : in std_logic;
45 FTDI_SIWUA : out std_logic;
46 FTDI_WR : out std_logic;
47 FTDI_RD : out std_logic;
48 FTDI_D_in : in std_logic_vector(7 downto 0);
49 FTDI_D_out : out std_logic_vector(7 downto 0);
50 FTDI_D_drive : out std_logic
51 );
52 end ftdi_async_fifo_loopback;
53
54 architecture beh of ftdi_async_fifo_loopback is
55
56 type fifo_fsm_st is (idle,waitTXE,preWrite,Write,postWrite,preRead,Read,postRead);
57 signal state : fifo_fsm_st:=idle;
58 signal output_en : std_logic;
59 signal dready : std_logic;
60 signal fifo_flush_cntr : integer := 31;
61 signal fifo_siwu_pulse : std_logic_vector(3 downto 0):= (others => '1');
62
63 begin
64
65 acthi: if oepol = 1 generate
66 output_en <= '1';
67 end generate;
68 actlow: if oepol = 0 generate
69 output_en <= '0';
70 end generate;
71
72 FTDI_SIWUA <= '1';--fifo_siwu_pulse(0);
73
74 process(rstn,clk)
75 begin
76 if rstn = '0' then
77 FTDI_RD <= '1';
78 FTDI_WR <= '1';
79 FTDI_D_drive <= not output_en;
80 elsif clk'event and clk='1' then
81 if fifo_flush_cntr = 1 then
82 fifo_siwu_pulse <= (others => '0');
83 else
84 fifo_siwu_pulse <= '1' & fifo_siwu_pulse(3 downto 1);
85 end if;
86 case state is
87 when idle =>
88 if FTDI_RXF = '0' then
89 state <= preRead;
90 FTDI_RD <= '0';
91 end if;
92 FTDI_WR <= '1';
93 when preWrite =>
94 FTDI_WR <= '0';
95 state <= Write;
96 when Write =>
97 FTDI_D_drive <= not output_en;
98 state <= idle;
99 fifo_flush_cntr <= 31;
100 when preRead =>
101 state <= Read;
102 when Read =>
103 FTDI_D_out <= FTDI_D_in;
104 FTDI_RD <= '1';
105 state <= waitTXE;
106 when waitTXE =>
107 if FTDI_TXE = '0' then
108 state <= preWrite;
109 FTDI_D_drive <= output_en;
110 end if;
111 when others => NULL;
112 end case;
113 end if;
114 end process;
115
116 end beh;
117
118 -- type dcom_uart_in_type is record
119 -- read : std_ulogic;
120 -- write : std_ulogic;
121 -- data : std_logic_vector(7 downto 0);
122 -- end record;
123
124 -- type dcom_uart_out_type is record
125 -- dready : std_ulogic; -> data from ftdi to DCOM
126 -- tsempty : std_ulogic; -> not used by decom -> set to 0
127 -- thempty : std_ulogic; -> tels dcom that ready to write to ftdi
128 -- lock : std_ulogic; -> set to 1
129 -- enable : std_ulogic; -> unused
130 -- data : std_logic_vector(7 downto 0);
131 -- end record;
132
This diff has been collapsed as it changes many lines, (739 lines changed) Show them Hide them
@@ -0,0 +1,739
1 --
2 -- AHB master for AMBA interface.
3 --
4 -- This is a helper entity for the SpaceWire AMBA interface.
5 -- It implements the AHB master which transfers data from/to main memory.
6 --
7 -- Descriptor flag bits on input:
8 -- bit 15:0 (RX) max nr of bytes to receive (must be a multiple of 4)
9 -- (TX) nr of bytes to transmit
10 -- bit 16 EN: '1' = descriptor enabled
11 -- bit 17 WR: wrap to beginning of descriptor table
12 -- bit 18 IE: interrupt at end of descriptor
13 -- bit 19 '0'
14 -- bit 20 (TX only) send EOP after end of data
15 -- bit 21 (TX only) send EEP after end of data
16 --
17 -- Descriptor flag bits after completion of frame:
18 -- bit 15:0 (RX only) LEN: nr of bytes received
19 -- (TX) undefined
20 -- bit 16 '0'
21 -- bit 18:17 undefined
22 -- bit 19 '1' to indicate descriptor completed
23 --- bit 20 (RX only) received EOP after end of data
24 -- bit 21 (RX only) received EEP after end of data
25 --
26
27 library ieee;
28 use ieee.std_logic_1164.all;
29 use ieee.numeric_std.all;
30 library grlib;
31 use grlib.amba.all;
32 use grlib.stdlib.all;
33 use work.spwambapkg.all;
34
35
36 entity spwahbmst is
37
38 generic (
39 -- AHB master index.
40 hindex: integer;
41
42 -- AHB plug&play information.
43 hconfig: ahb_config_type;
44
45 -- Maximum burst length as the 2-logarithm of the number of words.
46 maxburst: integer range 1 to 8
47 );
48
49 port (
50 -- System clock.
51 clk: in std_logic;
52
53 -- Synchronous reset (active-low).
54 rstn: in std_logic;
55
56 -- Inputs from SpaceWire core.
57 msti: in spw_ahbmst_in_type;
58
59 -- Outputs to SpaceWire core.
60 msto: out spw_ahbmst_out_type;
61
62 -- AHB master input signals.
63 ahbi: in ahb_mst_in_type;
64
65 -- AHB master output signals.
66 ahbo: out ahb_mst_out_type
67 );
68
69 end entity spwahbmst;
70
71 architecture spwahbmst_arch of spwahbmst is
72
73 --
74 -- Registers.
75 --
76
77 type state_type is (
78 st_idle,
79 st_rxgetdesc, st_rxgetptr, st_rxtransfer, st_rxfinal, st_rxputdesc,
80 st_txgetdesc, st_txgetptr, st_txtransfer, st_txfinal, st_txputdesc, st_txskip );
81
82 type burst_state_type is ( bs_idle, bs_setup, bs_active, bs_end );
83
84 type regs_type is record
85 -- dma state
86 rxdma_act: std_ulogic;
87 txdma_act: std_ulogic;
88 ahberror: std_ulogic;
89 -- main state machine
90 mstate: state_type;
91 firstword: std_ulogic;
92 prefertx: std_ulogic;
93 -- rx descriptor state
94 rxdes_en: std_ulogic;
95 rxdes_wr: std_ulogic;
96 rxdes_ie: std_ulogic;
97 rxdes_eop: std_ulogic;
98 rxdes_eep: std_ulogic;
99 rxdes_len: std_logic_vector(13 downto 0); -- in 32-bit words
100 rxdes_pos: std_logic_vector(15 downto 0); -- in bytes
101 rxaddr: std_logic_vector(31 downto 2);
102 rxdesc_next: std_ulogic;
103 -- tx descriptor state
104 txdes_en: std_ulogic;
105 txdes_wr: std_ulogic;
106 txdes_ie: std_ulogic;
107 txdes_eop: std_ulogic;
108 txdes_eep: std_ulogic;
109 txdes_len: std_logic_vector(15 downto 0); -- in bytes
110 txaddr: std_logic_vector(31 downto 2);
111 txdesc_next: std_ulogic;
112 -- interrupts
113 int_rxdesc: std_ulogic;
114 int_txdesc: std_ulogic;
115 int_rxpacket: std_ulogic;
116 -- burst state
117 burststat: burst_state_type;
118 hbusreq: std_ulogic;
119 hwrite: std_ulogic;
120 haddr: std_logic_vector(31 downto 2);
121 hwdata: std_logic_vector(31 downto 0);
122 end record;
123
124 constant regs_reset: regs_type := (
125 rxdma_act => '0',
126 txdma_act => '0',
127 ahberror => '0',
128 mstate => st_idle,
129 firstword => '0',
130 prefertx => '0',
131 rxdes_en => '0',
132 rxdes_wr => '0',
133 rxdes_ie => '0',
134 rxdes_eop => '0',
135 rxdes_eep => '0',
136 rxdes_len => (others => '0'),
137 rxdes_pos => (others => '0'),
138 rxaddr => (others => '0'),
139 rxdesc_next => '0',
140 txdes_en => '0',
141 txdes_wr => '0',
142 txdes_ie => '0',
143 txdes_eop => '0',
144 txdes_eep => '0',
145 txdes_len => (others => '0'),
146 txaddr => (others => '0'),
147 txdesc_next => '0',
148 int_rxdesc => '0',
149 int_txdesc => '0',
150 int_rxpacket => '0',
151 burststat => bs_idle,
152 hbusreq => '0',
153 hwrite => '0',
154 haddr => (others => '0'),
155 hwdata => (others => '0') );
156
157 signal r: regs_type := regs_reset;
158 signal rin: regs_type;
159
160 begin
161
162 --
163 -- Combinatorial process
164 --
165 process (r, rstn, msti, ahbi) is
166 variable v: regs_type;
167 variable v_hrdata: std_logic_vector(31 downto 0);
168 variable v_burstreq: std_logic;
169 variable v_burstack: std_logic;
170 variable v_rxfifo_read: std_logic;
171 variable v_txfifo_write: std_logic;
172 variable v_txfifo_wdata: std_logic_vector(35 downto 0);
173 begin
174 v := r;
175
176 -- Decode AHB data bus (64-bit AHB compatibility).
177 v_hrdata := ahbreadword(ahbi.hrdata);
178
179 -- Assume no burst request.
180 v_burstreq := '0';
181
182 -- Detect request from burst state machine for next data word.
183 v_burstack := ahbi.hready and
184 conv_std_logic(r.burststat = bs_active or r.burststat = bs_end);
185
186 -- Assume no fifo activity; take data for TX fifo from AHB bus.
187 v_rxfifo_read := '0';
188 v_txfifo_write := '0';
189 v_txfifo_wdata(35 downto 32) := (others => '0');
190 v_txfifo_wdata(31 downto 0) := v_hrdata;
191
192 -- Reset registers for interrupts and descriptor updates.
193 v.int_rxdesc := '0';
194 v.int_txdesc := '0';
195 v.int_rxpacket := '0';
196 v.rxdesc_next := '0';
197 v.txdesc_next := '0';
198
199 -- Start DMA on external request.
200 if msti.rxdma_start = '1' then v.rxdma_act := '1'; end if;
201 if msti.txdma_start = '1' then v.txdma_act := '1'; end if;
202
203 --
204 -- Main state machine.
205 --
206 case r.mstate is
207
208 when st_idle =>
209 -- Waiting for something to do.
210 v.prefertx := '0';
211 v.firstword := '1';
212 if msti.txdma_cancel = '1' then
213 v.txdma_act := '0';
214 v.txdes_en := '0';
215 end if;
216 if r.rxdma_act = '1' and msti.rxfifo_empty = '0' and
217 (r.prefertx = '0' or r.txdma_act = '0' or msti.txfifo_highw = '1') then
218 -- Start RX transfer.
219 if r.rxdes_en = '1' then
220 -- Transfer RX data to current descriptor.
221 v_burstreq := '1';
222 v.hwrite := '1';
223 v.haddr := r.rxaddr;
224 v.mstate := st_rxtransfer;
225 else
226 -- Must fetch new RX descriptor.
227 v_burstreq := '1';
228 v.hwrite := '0';
229 v.haddr := msti.rxdesc_ptr & "0";
230 v.mstate := st_rxgetdesc;
231 end if;
232 elsif r.txdma_act = '1' and msti.txdma_cancel = '0' and msti.txfifo_highw = '0' then
233 -- Start TX transfer.
234 if r.txdes_en = '1' then
235 -- Transfer TX data from current descriptor.
236 if unsigned(r.txdes_len) = 0 then
237 -- Only send EOP/EEP and write back descriptor.
238 v_burstreq := '1';
239 v.hwrite := '1';
240 v.haddr := msti.txdesc_ptr & "0";
241 v.txdesc_next := '1';
242 v.mstate := st_txputdesc;
243 else
244 -- Start burst transfer.
245 v_burstreq := '1';
246 v.hwrite := '0';
247 v.haddr := r.txaddr;
248 if unsigned(r.txdes_len) <= 4 then
249 -- Transfer only one word.
250 v.mstate := st_txfinal;
251 else
252 v.mstate := st_txtransfer;
253 end if;
254 end if;
255 else
256 -- Must fetch new TX descriptor.
257 v_burstreq := '1';
258 v.hwrite := '0';
259 v.haddr := msti.txdesc_ptr & "0";
260 v.mstate := st_txgetdesc;
261 end if;
262 end if;
263
264 when st_rxgetdesc =>
265 -- Read RX descriptor flags from memory.
266 v_burstreq := '1';
267 v.hwrite := '0';
268 v.rxdes_len := v_hrdata(15 downto 2);
269 v.rxdes_en := v_hrdata(16);
270 v.rxdes_wr := v_hrdata(17);
271 v.rxdes_ie := v_hrdata(18);
272 v.rxdes_eop := '0';
273 v.rxdes_eep := '0';
274 v.rxdes_pos := (others => '0');
275 if v_burstack = '1' then
276 -- Got descriptor flags.
277 v_burstreq := '0';
278 v.mstate := st_rxgetptr;
279 end if;
280
281 when st_rxgetptr =>
282 -- Read RX data pointer from memory.
283 v.rxaddr := v_hrdata(31 downto 2);
284 v.haddr := v_hrdata(31 downto 2);
285 v.firstword := '1';
286 if v_burstack = '1' then
287 -- Got data pointer.
288 if r.rxdes_en = '1' then
289 -- Start transfer.
290 v_burstreq := '1';
291 v.hwrite := '1';
292 v.mstate := st_rxtransfer;
293 else
294 -- Reached end of valid descriptors; stop.
295 v.rxdma_act := '0';
296 v.mstate := st_idle;
297 end if;
298 end if;
299
300 when st_rxtransfer =>
301 -- Continue an RX transfer.
302 v_burstreq := '1';
303 v.hwrite := '1';
304 v.firstword := '0';
305 if v_burstack = '1' or r.firstword = '1' then
306 -- Setup first/next data word.
307 v.hwdata := msti.rxfifo_rdata(31 downto 0);
308 v_rxfifo_read := '1';
309 -- Update pointers.
310 v.rxdes_len := std_logic_vector(unsigned(r.rxdes_len) - 1);
311 v.rxdes_pos := std_logic_vector(unsigned(r.rxdes_pos) + 4);
312 v.rxaddr := std_logic_vector(unsigned(r.rxaddr) + 1);
313 -- Detect EOP/EEP.
314 v.rxdes_eop :=
315 (msti.rxfifo_rdata(35) and not msti.rxfifo_rdata(24)) or
316 (msti.rxfifo_rdata(34) and not msti.rxfifo_rdata(16)) or
317 (msti.rxfifo_rdata(33) and not msti.rxfifo_rdata(8)) or
318 (msti.rxfifo_rdata(32) and not msti.rxfifo_rdata(0));
319 v.rxdes_eep :=
320 (msti.rxfifo_rdata(35) and msti.rxfifo_rdata(24)) or
321 (msti.rxfifo_rdata(34) and msti.rxfifo_rdata(16)) or
322 (msti.rxfifo_rdata(33) and msti.rxfifo_rdata(8)) or
323 (msti.rxfifo_rdata(32) and msti.rxfifo_rdata(0));
324 -- Adjust frame length in case of EOP/EEP.
325 if msti.rxfifo_rdata(35) = '1' then
326 v.rxdes_pos := r.rxdes_pos(r.rxdes_pos'high downto 2) & "00";
327 elsif msti.rxfifo_rdata(34) = '1' then
328 v.rxdes_pos := r.rxdes_pos(r.rxdes_pos'high downto 2) & "01";
329 elsif msti.rxfifo_rdata(33) = '1' then
330 v.rxdes_pos := r.rxdes_pos(r.rxdes_pos'high downto 2) & "10";
331 elsif msti.rxfifo_rdata(32) = '1' then
332 v.rxdes_pos := r.rxdes_pos(r.rxdes_pos'high downto 2) & "11";
333 end if;
334 -- Stop at end of requested length or end of packet or fifo empty.
335 if msti.rxfifo_nxempty = '1' or
336 orv(msti.rxfifo_rdata(35 downto 32)) = '1' or
337 unsigned(r.rxdes_len) = 1 then
338 v_burstreq := '0';
339 v.mstate := st_rxfinal;
340 end if;
341 -- Stop at max burst length boundary.
342 if (andv(r.rxaddr(maxburst+1 downto 2)) = '1') then
343 v_burstreq := '0';
344 v.mstate := st_rxfinal;
345 end if;
346 end if;
347
348 when st_rxfinal =>
349 -- Last data cycle of an RX transfer.
350 if v_burstack = '1' then
351 if unsigned(r.rxdes_len) = 0 or
352 r.rxdes_eop = '1' or r.rxdes_eep = '1' then
353 -- End of frame; write back descriptor.
354 v_burstreq := '1';
355 v.hwrite := '1';
356 v.haddr := msti.rxdesc_ptr & "0";
357 v.rxdesc_next := '1';
358 v.mstate := st_rxputdesc;
359 else
360 -- Go through st_idle to pick up more work.
361 v.mstate := st_idle;
362 end if;
363 end if;
364 -- Give preference to TX work since we just did some RX work.
365 v.prefertx := '1';
366
367 when st_rxputdesc =>
368 -- Write back RX descriptor.
369 v.hwdata(15 downto 0) := r.rxdes_pos;
370 v.hwdata(16) := '0';
371 v.hwdata(17) := r.rxdes_wr;
372 v.hwdata(18) := r.rxdes_ie;
373 v.hwdata(19) := '1';
374 v.hwdata(20) := r.rxdes_eop;
375 v.hwdata(21) := r.rxdes_eep;
376 v.hwdata(31 downto 22) := (others => '0');
377 if v_burstack = '1' then
378 -- Frame done.
379 v.rxdes_en := '0';
380 v.int_rxdesc := r.rxdes_ie;
381 v.int_rxpacket := r.rxdes_eop or r.rxdes_eep;
382 -- Go to st_idle.
383 v.mstate := st_idle;
384 end if;
385
386 when st_txgetdesc =>
387 -- Read TX descriptor flags from memory.
388 v_burstreq := '1';
389 v.hwrite := '0';
390 v.txdes_len := v_hrdata(15 downto 0);
391 v.txdes_en := v_hrdata(16);
392 v.txdes_wr := v_hrdata(17);
393 v.txdes_ie := v_hrdata(18);
394 v.txdes_eop := v_hrdata(20);
395 v.txdes_eep := v_hrdata(21);
396 if v_burstack = '1' then
397 -- Got descriptor flags.
398 v_burstreq := '0';
399 v.mstate := st_txgetptr;
400 end if;
401
402 when st_txgetptr =>
403 -- Read TX data pointer from memory.
404 v.txaddr := v_hrdata(31 downto 2);
405 if v_burstack = '1' then
406 -- Got data pointer.
407 if r.txdes_en = '1' then
408 -- Start transfer.
409 if unsigned(r.txdes_len) = 0 then
410 -- Only send EOP/EEP and write back descriptor.
411 v_burstreq := '1';
412 v.hwrite := '1';
413 v.haddr := msti.txdesc_ptr & "0";
414 v.txdesc_next := '1';
415 v.mstate := st_txputdesc;
416 else
417 v_burstreq := '1';
418 v.hwrite := '0';
419 v.haddr := v_hrdata(31 downto 2);
420 if unsigned(r.txdes_len) <= 4 then
421 -- Transfer only one word.
422 v.mstate := st_txfinal;
423 else
424 v.mstate := st_txtransfer;
425 end if;
426 end if;
427 else
428 -- Reached end of valid descriptors; stop.
429 v.txdma_act := '0';
430 v.mstate := st_idle;
431 end if;
432 end if;
433
434 when st_txtransfer =>
435 -- Continue an TX transfer.
436 v_burstreq := '1';
437 v.hwrite := '0';
438 if v_burstack = '1' then
439 -- Got next data word from memory.
440 v_txfifo_write := '1';
441 -- Update pointers.
442 v.txdes_len := std_logic_vector(unsigned(r.txdes_len) - 4);
443 v.txaddr := std_logic_vector(unsigned(r.txaddr) + 1);
444 -- Handle end of burst/transfer.
445 if andv(r.txaddr(maxburst+1 downto 2)) = '1' then
446 -- This was the last data cycle before the max burst boundary.
447 -- Go through st_idle to pick up more work.
448 v_burstreq := '0';
449 v.mstate := st_idle;
450 elsif msti.txfifo_nxfull = '1' then
451 -- Fifo full; stop transfer, ignore final data cycle.
452 v_burstreq := '0';
453 v.mstate := st_txskip;
454 elsif unsigned(r.txdes_len) <= 8 then
455 -- Stop at end of requested length (one more data cycle).
456 v_burstreq := '0';
457 v.mstate := st_txfinal;
458 elsif andv(r.txaddr(maxburst+1 downto 3)) = '1' then
459 -- Stop at max burst length boundary (one more data cycle).
460 v_burstreq := '0';
461 end if;
462 else
463 if andv(r.txaddr(maxburst+1 downto 2)) = '1' then
464 -- Stop at max burst length boundary (just one more data cycle).
465 v_burstreq := '0';
466 end if;
467 end if;
468
469 when st_txfinal =>
470 -- Last data cycle of a TX descriptor (1 <= txdes_len <= 4).
471 if v_burstack = '1' then
472 -- Got last data word from memory.
473 v_txfifo_write := '1';
474 v.txdes_len := std_logic_vector(unsigned(r.txdes_len) - 4);
475 -- Insert EOP in last word if needed.
476 -- (Or set bit 7 in the flag byte to indicate that the
477 -- frame ends while the packet continues.)
478 case r.txdes_len(1 downto 0) is
479 when "01" =>
480 v_txfifo_wdata(34) := '1';
481 v_txfifo_wdata(23) := not (r.txdes_eop or r.txdes_eep);
482 v_txfifo_wdata(22 downto 17) := "000000";
483 v_txfifo_wdata(16) := r.txdes_eep;
484 when "10" =>
485 v_txfifo_wdata(33) := '1';
486 v_txfifo_wdata(15) := not (r.txdes_eop or r.txdes_eep);
487 v_txfifo_wdata(14 downto 9) := "000000";
488 v_txfifo_wdata(8) := r.txdes_eep;
489 when "11" =>
490 v_txfifo_wdata(32) := '1';
491 v_txfifo_wdata(7) := not (r.txdes_eop or r.txdes_eep);
492 v_txfifo_wdata(6 downto 1) := "000000";
493 v_txfifo_wdata(0) := r.txdes_eep;
494 when others =>
495 -- txdes_len = 4
496 -- Store 4 data bytes now; store EOP in st_txputdesc (if needed).
497 end case;
498 if msti.txfifo_nxfull = '1' and r.txdes_len(1 downto 0) = "00" then
499 -- Fifo full so no room to store EOP.
500 v.mstate := st_idle;
501 v.haddr := msti.txdesc_ptr & "0";
502 else
503 -- Prepare to write back descriptor.
504 v_burstreq := '1';
505 v.hwrite := '1';
506 v.haddr := msti.txdesc_ptr & "0";
507 v.txdesc_next := '1';
508 v.mstate := st_txputdesc;
509 end if;
510 end if;
511
512 when st_txputdesc =>
513 -- Write back TX descriptor.
514 v.hwdata(15 downto 0) := (others => '0');
515 v.hwdata(16) := '0';
516 v.hwdata(17) := r.txdes_wr;
517 v.hwdata(18) := r.txdes_ie;
518 v.hwdata(19) := '1';
519 v.hwdata(20) := r.txdes_eop;
520 v.hwdata(21) := r.txdes_eep;
521 v.hwdata(31 downto 22) := (others => '0');
522 if v_burstack = '1' then
523 if r.txdes_len(1 downto 0) = "00" and
524 (r.txdes_eop = '1' or r.txdes_eep = '1') then
525 -- Store EOP in TX fifo.
526 v_txfifo_write := '1';
527 v_txfifo_wdata(35) := '1';
528 v_txfifo_wdata(31 downto 25) := "0000000";
529 v_txfifo_wdata(24) := r.txdes_eep;
530 end if;
531 -- Frame done.
532 v.txdes_en := '0';
533 v.int_txdesc := r.txdes_ie;
534 -- Go to st_idle and give preference to RX work.
535 v.mstate := st_idle;
536 end if;
537
538 when st_txskip =>
539 -- Ignore last data cycle of burst because TX fifo is full.
540 if v_burstack = '1' then
541 v.mstate := st_idle;
542 end if;
543
544 end case;
545
546 -- Abort DMA when an AHB error occurs.
547 if r.ahberror = '1' then
548 v.rxdma_act := '0';
549 v.txdma_act := '0';
550 v.mstate := st_idle;
551 end if;
552
553
554 --
555 -- Burst state machine.
556 --
557 -- A transfer starts when the main state machine combinatorially pulls
558 -- v_burstreq high and assigns v.haddr and v.hwrite (i.e. r.haddr and
559 -- r.hwrite must be valid in the first clock cycle AFTER rising v_burstreq).
560 -- In case of a write transfer, r.hwdata must be valid in the second
561 -- clock cycle after rising v_burstreq.
562 --
563 -- During the transfer, the burst state machine announces each word
564 -- with a v_burstack pulse. During a read transfer, ahbi.hrdata is
565 -- valid when v_burstack is high. During a write transfer, a next
566 -- word must be assigned to v.hwdata on the v_burstack pulse.
567 --
568 -- For a single-word transfer, v_burstreq should be high for only one
569 -- clock cycle. For a multi-word transfer, v_burstreq should be high
570 -- until the last-but-one v_burstack pulse. I.e. after v_burstreq is
571 -- released combinatorially on a v_burstack pulse, one last v_burstack
572 -- pulse will follow.
573 --
574 -- The burst state machine transparently handles bus arbitration and
575 -- retrying of transfers. In case of a non-retryable error, r.ahberror
576 -- is set high and further transfers are blocked. The main state
577 -- machine is responsible for ensuring that bursts do not cross a
578 -- forbidden address boundary.
579 --
580 case r.burststat is
581
582 when bs_idle =>
583 -- Wait for request and bus grant.
584 -- (htrans = HTRANS_IDLE)
585 v.hbusreq := r.hbusreq or v_burstreq;
586 if (r.hbusreq = '1' or v_burstreq = '1') and
587 ahbi.hready = '1' and
588 ahbi.hgrant(hindex) = '1' then
589 -- Start burst.
590 v.burststat := bs_setup;
591 end if;
592 -- Block new bursts after an error occurred.
593 if r.ahberror = '1' then
594 v.hbusreq := '0';
595 v.burststat := bs_idle;
596 end if;
597
598 when bs_setup =>
599 -- First address cycle.
600 -- (htrans = HTRANS_NONSEQ)
601 v.hbusreq := '1';
602 if ahbi.hready = '1' then
603 -- Increment address and continue burst in bs_active.
604 v.haddr(maxburst+1 downto 2) := std_logic_vector(unsigned(r.haddr(maxburst+1 downto 2)) + 1);
605 v.burststat := bs_active;
606 -- Stop burst when application ends the transfer.
607 v.hbusreq := v_burstreq;
608 if v_burstreq = '0' then
609 v.burststat := bs_end;
610 end if;
611 -- Stop burst when we are kicked off the bus.
612 if ahbi.hgrant(hindex) = '0' then
613 v.burststat := bs_end;
614 end if;
615 end if;
616
617 when bs_active =>
618 -- Continue burst.
619 -- (htrans = HTRANS_SEQ)
620 v.hbusreq := '1';
621 if ahbi.hresp /= HRESP_OKAY then
622 -- Error response from slave.
623 v.haddr(maxburst+1 downto 2) := std_logic_vector(unsigned(r.haddr(maxburst+1 downto 2)) - 1);
624 if ahbi.hresp = HRESP_ERROR then
625 -- Permanent error.
626 v.ahberror := '1';
627 v.hbusreq := '0';
628 else
629 -- Must retry request.
630 v.hbusreq := '1';
631 end if;
632 v.burststat := bs_idle;
633 elsif ahbi.hready = '1' then
634 -- Increment address.
635 v.haddr(maxburst+1 downto 2) := std_logic_vector(unsigned(r.haddr(maxburst+1 downto 2)) + 1);
636 -- Stop burst when application ends the transfer.
637 v.hbusreq := v_burstreq;
638 if v_burstreq = '0' then
639 v.burststat := bs_end;
640 end if;
641 -- Stop burst when we are kicked off the bus.
642 if ahbi.hgrant(hindex) = '0' then
643 v.burststat := bs_end;
644 end if;
645 end if;
646
647 when bs_end =>
648 -- Last data cycle of burst.
649 -- (htrans = HTRANS_IDLE)
650 v.hbusreq := r.hbusreq or v_burstreq;
651 if ahbi.hresp /= HRESP_OKAY then
652 -- Error response from slave.
653 v.haddr(maxburst+1 downto 2) := std_logic_vector(unsigned(r.haddr(maxburst+1 downto 2)) - 1);
654 if ahbi.hresp = HRESP_ERROR then
655 -- Permanent error.
656 v.ahberror := '1';
657 v.hbusreq := '0';
658 else
659 -- Must retry request.
660 v.hbusreq := '1';
661 end if;
662 v.burststat := bs_idle;
663 elsif ahbi.hready = '1' then
664 -- Burst complete.
665 if (r.hbusreq = '1' or v_burstreq = '1') and
666 ahbi.hgrant(hindex) = '1' then
667 -- Immediately start next burst.
668 v.burststat := bs_setup;
669 else
670 v.burststat := bs_idle;
671 end if;
672 end if;
673
674 end case;
675
676
677 --
678 -- Drive output signals.
679 --
680 ahbo.hbusreq <= r.hbusreq;
681 if r.burststat = bs_setup then
682 ahbo.htrans <= HTRANS_NONSEQ;
683 elsif r.burststat = bs_active then
684 ahbo.htrans <= HTRANS_SEQ;
685 else
686 ahbo.htrans <= HTRANS_IDLE;
687 end if;
688 ahbo.haddr <= r.haddr & "00";
689 ahbo.hwrite <= r.hwrite;
690 ahbo.hwdata <= ahbdrivedata(r.hwdata);
691 ahbo.hlock <= '0'; -- never lock the bus
692 ahbo.hsize <= HSIZE_WORD; -- always 32-bit words
693 ahbo.hburst <= HBURST_INCR; -- undetermined incremental burst
694 ahbo.hprot <= "0011"; -- not cacheable, privileged, data
695 ahbo.hirq <= (others => '0'); -- no interrupts via AHB bus
696 ahbo.hconfig <= hconfig; -- AHB plug&play data
697 ahbo.hindex <= hindex; -- index feedback
698
699 msto.rxdma_act <= r.rxdma_act;
700 msto.txdma_act <= r.txdma_act;
701 msto.ahberror <= r.ahberror;
702 msto.int_rxdesc <= r.int_rxdesc;
703 msto.int_txdesc <= r.int_txdesc;
704 msto.int_rxpacket <= r.int_rxpacket;
705 msto.rxdesc_next <= r.rxdesc_next;
706 msto.rxdesc_wrap <= r.rxdesc_next and r.rxdes_wr;
707 msto.txdesc_next <= r.txdesc_next;
708 msto.txdesc_wrap <= r.txdesc_next and r.txdes_wr;
709 msto.rxfifo_read <= v_rxfifo_read;
710 msto.txfifo_write <= v_txfifo_write;
711 msto.txfifo_wdata <= v_txfifo_wdata;
712
713
714 --
715 -- Reset.
716 --
717 if rstn = '0' then
718 v := regs_reset;
719 end if;
720
721
722 --
723 -- Update registers.
724 --
725 rin <= v;
726 end process;
727
728
729 --
730 -- Synchronous process: update registers.
731 --
732 process (clk) is
733 begin
734 if rising_edge(clk) then
735 r <= rin;
736 end if;
737 end process;
738
739 end architecture spwahbmst_arch;
This diff has been collapsed as it changes many lines, (886 lines changed) Show them Hide them
@@ -0,0 +1,886
1 --
2 -- SpaceWire core with AMBA interface.
3 --
4 -- APB registers:
5 --
6 -- Address 0x00: Control Register
7 -- bit 0 Reset spwamba core (auto-clear)
8 -- bit 1 Reset DMA engines (auto-clear)
9 -- bit 2 Link start
10 -- bit 3 Link autostart
11 -- bit 4 Link disable
12 -- bit 5 Enable timecode transmission through tick_in signal
13 -- bit 6 Start RX DMA (auto-clear)
14 -- bit 7 Start TX DMA (auto-clear)
15 -- bit 8 Cancel TX DMA and discard TX data queue (auto-clear)
16 -- bit 9 Enable interrupt on link up/down
17 -- bit 10 Enable interrupt on time code received
18 -- bit 11 Enable interrupt on RX descriptor
19 -- bit 12 Enable interrupt on TX descriptor
20 -- bit 13 Enable interrupt on RX packet
21 -- bit 27:24 desctablesize (read-only)
22 --
23 -- Address 0x04: Status Register
24 -- bit 1:0 Link status: 0=off, 1=started, 2=connecting, 3=run
25 -- bit 2 Got disconnect error (sticky)
26 -- bit 3 Got parity error (sticky)
27 -- bit 4 Got escape error (sticky)
28 -- bit 5 Got credit error (sticky)
29 -- bit 6 RX DMA enabled
30 -- bit 7 TX DMA enabled
31 -- bit 8 AHB error occurred (reset DMA engine to clear)
32 -- bit 9 Reserved
33 -- bit 10 Received timecode (sticky)
34 -- bit 11 Finished RX descriptor with IE='1' (sticky)
35 -- bit 12 Finished TX descriptor with IE='1' (sticky)
36 -- bit 13 Received packet (sticky)
37 -- bit 14 RX buffer empty after packet
38 --
39 -- Sticky bits are reset by writing a '1' bit to the corresponding
40 -- bit position(s).
41 --
42 -- Address 0x08: Transmission Clock Scaler
43 -- bit 7:0 txclk division factor minus 1
44 --
45 -- Address 0x0c: Timecode Register
46 -- bit 5:0 Last received timecode value (read-only)
47 -- bit 7:6 Control bits received with last timecode (read-only)
48 -- bit 13:8 Timecode value to send on next tick_in (auto-increment)
49 -- bit 15:14 Reserved (write as zero)
50 -- bit 16 Write '1' to send a timecode (auto-clear)
51 --
52 -- Address 0x10: Descriptor pointer for RX DMA
53 -- bit 2:0 Reserved, write as zero
54 -- bit desctablesize+2:3 Descriptor index (auto-increment)
55 -- bit 31:desctablesize+3 Fixed address bits of descriptor table
56 --
57 -- For example, if desctablesize = 10, a 8192-byte area is
58 -- determined by bits 31:13. This area has room for 1024 descriptors
59 -- of 8 bytes each. Bits 12:3 point to the current descriptor within
60 -- the table.
61 --
62 -- Address 0x14: Descriptor pointer for TX DMA
63 -- bit 2:0 Reserved, write as zero
64 -- bit desctablesize+2:3 Descriptor index (auto-increment)
65 -- bit 31:desctablesize+3 Fixed address bits of descriptor table
66 --
67
68 library ieee;
69 use ieee.std_logic_1164.all;
70 use ieee.numeric_std.all;
71 library techmap;
72 use techmap.gencomp.all;
73 library grlib;
74 use grlib.amba.all;
75 use grlib.devices.all;
76 use grlib.stdlib.all;
77 use work.spwpkg.all;
78 use work.spwambapkg.all;
79
80 entity spwamba is
81
82 generic (
83 -- Technology selection for FIFO memories.
84 tech: integer range 0 to NTECH := DEFFABTECH;
85
86 -- AHB master index.
87 hindex: integer;
88
89 -- APB slave index.
90 pindex: integer;
91
92 -- Bits 19 to 8 of the APB address range.
93 paddr: integer;
94
95 -- Mask for APB address bits 19 to 8.
96 pmask: integer := 16#fff#;
97
98 -- Index of the interrupt request line.
99 pirq: integer;
100
101 -- System clock frequency in Hz.
102 -- This must be set to the frequency of "clk". It is used to setup
103 -- counters for reset timing, disconnect timeout and to transmit
104 -- at 10 Mbit/s during the link handshake.
105 sysfreq: real;
106
107 -- Transmit clock frequency in Hz (only if tximpl = impl_fast).
108 -- This must be set to the frequency of "txclk". It is used to
109 -- transmit at 10 Mbit/s during the link handshake.
110 txclkfreq: real := 0.0;
111
112 -- Selection of a receiver front-end implementation.
113 rximpl: spw_implementation_type := impl_generic;
114
115 -- Maximum number of bits received per system clock
116 -- (must be 1 in case of impl_generic).
117 rxchunk: integer range 1 to 4 := 1;
118
119 -- Selection of a transmitter implementation.
120 tximpl: spw_implementation_type := impl_generic;
121
122 -- Enable capability to generate time-codes.
123 timecodegen: boolean := true;
124
125 -- Size of the receive FIFO as the 2-logarithm of the number of words.
126 -- Must be at least 6 (64 words = 256 bytes).
127 rxfifosize: integer range 6 to 12 := 8;
128
129 -- Size of the transmit FIFO as the 2-logarithm of the number of words.
130 txfifosize: integer range 2 to 12 := 8;
131
132 -- Size of the DMA descriptor tables as the 2-logarithm of the number
133 -- of descriptors.
134 desctablesize: integer range 4 to 14 := 10;
135
136 -- Maximum burst length as the 2-logarithm of the number of words (default 8 words).
137 maxburst: integer range 1 to 8 := 3
138 );
139
140 port (
141 -- System clock.
142 clk: in std_logic;
143
144 -- Receiver sample clock (only for impl_fast)
145 rxclk: in std_logic;
146
147 -- Transmit clock (only for impl_fast)
148 txclk: in std_logic;
149
150 -- Synchronous reset (active-low).
151 rstn: in std_logic;
152
153 -- APB slave input signals.
154 apbi: in apb_slv_in_type;
155
156 -- APB slave output signals.
157 apbo: out apb_slv_out_type;
158
159 -- AHB master input signals.
160 ahbi: in ahb_mst_in_type;
161
162 -- AHB master output signals.
163 ahbo: out ahb_mst_out_type;
164
165 -- Pulse for TimeCode generation.
166 tick_in: in std_logic;
167
168 -- High for one clock cycle if a TimeCode was just received.
169 tick_out: out std_logic;
170
171 -- Data In signal from SpaceWire bus.
172 spw_di: in std_logic;
173
174 -- Strobe In signal from SpaceWire bus.
175 spw_si: in std_logic;
176
177 -- Data Out signal to SpaceWire bus.
178 spw_do: out std_logic;
179
180 -- Strobe Out signal to SpaceWire bus.
181 spw_so: out std_logic
182 );
183
184 end entity spwamba;
185
186 architecture spwamba_arch of spwamba is
187
188 -- Reset time (6.4 us) in system clocks
189 constant reset_time: integer := integer(sysfreq * 6.4e-6);
190
191 -- Disconnect time (850 ns) in system clocks
192 constant disconnect_time: integer := integer(sysfreq * 850.0e-9);
193
194 -- Initial tx clock scaler (10 Mbit).
195 type impl_to_real_type is array(spw_implementation_type) of real;
196 constant tximpl_to_txclk_freq: impl_to_real_type :=
197 (impl_generic => sysfreq, impl_fast => txclkfreq);
198 constant effective_txclk_freq: real := tximpl_to_txclk_freq(tximpl);
199 constant default_divcnt: std_logic_vector(7 downto 0) :=
200 std_logic_vector(to_unsigned(integer(effective_txclk_freq / 10.0e6 - 1.0), 8));
201
202 -- Registers.
203 type regs_type is record
204 -- packet state
205 rxpacket: std_logic; -- '1' when receiving a packet
206 rxeep: std_logic; -- '1' when rx EEP character pending
207 txpacket: std_logic; -- '1' when transmitting a packet
208 txdiscard: std_logic; -- '1' when discarding a tx packet
209 -- RX fifo state
210 rxfifo_raddr: std_logic_vector(rxfifosize-1 downto 0);
211 rxfifo_waddr: std_logic_vector(rxfifosize-1 downto 0);
212 rxfifo_wdata: std_logic_vector(35 downto 0);
213 rxfifo_write: std_ulogic;
214 rxfifo_empty: std_ulogic;
215 rxfifo_bytemsk: std_logic_vector(2 downto 0);
216 rxroom: std_logic_vector(5 downto 0);
217 -- TX fifo state
218 txfifo_raddr: std_logic_vector(txfifosize-1 downto 0);
219 txfifo_waddr: std_logic_vector(txfifosize-1 downto 0);
220 txfifo_empty: std_ulogic;
221 txfifo_nxfull: std_ulogic;
222 txfifo_highw: std_ulogic;
223 txfifo_bytepos: std_logic_vector(1 downto 0);
224 -- APB registers
225 ctl_reset: std_ulogic;
226 ctl_resetdma: std_ulogic;
227 ctl_linkstart: std_ulogic;
228 ctl_autostart: std_ulogic;
229 ctl_linkdis: std_ulogic;
230 ctl_ticken: std_ulogic;
231 ctl_rxstart: std_ulogic;
232 ctl_txstart: std_ulogic;
233 ctl_txcancel: std_ulogic;
234 ctl_ielink: std_ulogic;
235 ctl_ietick: std_ulogic;
236 ctl_ierxdesc: std_ulogic;
237 ctl_ietxdesc: std_ulogic;
238 ctl_ierxpacket: std_ulogic;
239 sta_link: std_logic_vector(1 downto 0);
240 sta_errdisc: std_ulogic;
241 sta_errpar: std_ulogic;
242 sta_erresc: std_ulogic;
243 sta_errcred: std_ulogic;
244 sta_gottick: std_ulogic;
245 sta_rxdesc: std_ulogic;
246 sta_txdesc: std_ulogic;
247 sta_rxpacket: std_ulogic;
248 sta_rxempty: std_ulogic;
249 txdivcnt: std_logic_vector(7 downto 0);
250 time_in: std_logic_vector(5 downto 0);
251 tick_in: std_ulogic;
252 rxdesc_ptr: std_logic_vector(31 downto 3);
253 txdesc_ptr: std_logic_vector(31 downto 3);
254 -- APB interrupt request
255 irq: std_ulogic;
256 end record;
257
258 constant regs_reset: regs_type := (
259 rxpacket => '0',
260 rxeep => '0',
261 txpacket => '0',
262 txdiscard => '0',
263 rxfifo_raddr => (others => '0'),
264 rxfifo_waddr => (others => '0'),
265 rxfifo_wdata => (others => '0'),
266 rxfifo_write => '0',
267 rxfifo_empty => '1',
268 rxfifo_bytemsk => "111",
269 rxroom => (others => '1'),
270 txfifo_raddr => (others => '0'),
271 txfifo_waddr => (others => '0'),
272 txfifo_empty => '1',
273 txfifo_nxfull => '0',
274 txfifo_highw => '0',
275 txfifo_bytepos => "00",
276 ctl_reset => '0',
277 ctl_resetdma => '0',
278 ctl_linkstart => '0',
279 ctl_autostart => '0',
280 ctl_linkdis => '0',
281 ctl_ticken => '0',
282 ctl_rxstart => '0',
283 ctl_txstart => '0',
284 ctl_txcancel => '0',
285 ctl_ielink => '0',
286 ctl_ietick => '0',
287 ctl_ierxdesc => '0',
288 ctl_ietxdesc => '0',
289 ctl_ierxpacket => '0',
290 sta_link => "00",
291 sta_errdisc => '0',
292 sta_errpar => '0',
293 sta_erresc => '0',
294 sta_errcred => '0',
295 sta_gottick => '0',
296 sta_rxdesc => '0',
297 sta_txdesc => '0',
298 sta_rxpacket => '0',
299 sta_rxempty => '1',
300 txdivcnt => default_divcnt,
301 time_in => (others => '0'),
302 tick_in => '0',
303 rxdesc_ptr => (others => '0'),
304 txdesc_ptr => (others => '0'),
305 irq => '0' );
306
307 signal r: regs_type := regs_reset;
308 signal rin: regs_type;
309
310 -- Component interface signals.
311 signal recv_rxen: std_logic;
312 signal recvo: spw_recv_out_type;
313 signal recv_inact: std_logic;
314 signal recv_inbvalid: std_logic;
315 signal recv_inbits: std_logic_vector(rxchunk-1 downto 0);
316 signal xmit_rst: std_logic;
317 signal xmiti: spw_xmit_in_type;
318 signal xmito: spw_xmit_out_type;
319 signal xmit_divcnt: std_logic_vector(7 downto 0);
320 signal link_rst: std_logic;
321 signal linki: spw_link_in_type;
322 signal linko: spw_link_out_type;
323 signal msti: spw_ahbmst_in_type;
324 signal msto: spw_ahbmst_out_type;
325 signal ahbmst_rstn: std_logic;
326
327 -- Memory interface signals.
328 signal s_rxfifo_raddr: std_logic_vector(rxfifosize-1 downto 0);
329 signal s_rxfifo_rdata: std_logic_vector(35 downto 0);
330 signal s_rxfifo_wen: std_logic;
331 signal s_rxfifo_waddr: std_logic_vector(rxfifosize-1 downto 0);
332 signal s_rxfifo_wdata: std_logic_vector(35 downto 0);
333 signal s_txfifo_raddr: std_logic_vector(txfifosize-1 downto 0);
334 signal s_txfifo_rdata: std_logic_vector(35 downto 0);
335 signal s_txfifo_wen: std_logic;
336 signal s_txfifo_waddr: std_logic_vector(txfifosize-1 downto 0);
337 signal s_txfifo_wdata: std_logic_vector(35 downto 0);
338
339
340 -- APB slave plug&play configuration
341 constant REVISION: integer := 0;
342 constant pconfig: apb_config_type := (
343 0 => ahb_device_reg(VENDOR_OPENCORES, DEVICE_SPACEWIRELIGHT, 0, REVISION, pirq),
344 1 => apb_iobar(paddr, pmask) );
345
346 -- AHB master plug&play configuration
347 constant hconfig: ahb_config_type := (
348 0 => ahb_device_reg(VENDOR_OPENCORES, DEVICE_SPACEWIRELIGHT, 0, REVISION, 0),
349 others => zero32 );
350
351 begin
352
353 -- Instantiate link controller.
354 link_inst: spwlink
355 generic map (
356 reset_time => reset_time )
357 port map (
358 clk => clk,
359 rst => link_rst,
360 linki => linki,
361 linko => linko,
362 rxen => recv_rxen,
363 recvo => recvo,
364 xmiti => xmiti,
365 xmito => xmito );
366
367 -- Instantiate receiver.
368 recv_inst: spwrecv
369 generic map(
370 disconnect_time => disconnect_time,
371 rxchunk => rxchunk )
372 port map (
373 clk => clk,
374 rxen => recv_rxen,
375 recvo => recvo,
376 inact => recv_inact,
377 inbvalid => recv_inbvalid,
378 inbits => recv_inbits );
379
380 -- Instantiate receiver front-end.
381 recvfront_sel0: if rximpl = impl_generic generate
382 recvfront_generic_inst: spwrecvfront_generic
383 port map (
384 clk => clk,
385 rxen => recv_rxen,
386 inact => recv_inact,
387 inbvalid => recv_inbvalid,
388 inbits => recv_inbits,
389 spw_di => spw_di,
390 spw_si => spw_si );
391 end generate;
392 recvfront_sel1: if rximpl = impl_fast generate
393 recvfront_fast_inst: spwrecvfront_fast
394 generic map (
395 rxchunk => rxchunk )
396 port map (
397 clk => clk,
398 rxclk => rxclk,
399 rxen => recv_rxen,
400 inact => recv_inact,
401 inbvalid => recv_inbvalid,
402 inbits => recv_inbits,
403 spw_di => spw_di,
404 spw_si => spw_si );
405 end generate;
406
407 -- Instantiate transmitter.
408 xmit_sel0: if tximpl = impl_generic generate
409 xmit_inst: spwxmit
410 port map (
411 clk => clk,
412 rst => xmit_rst,
413 divcnt => xmit_divcnt,
414 xmiti => xmiti,
415 xmito => xmito,
416 spw_do => spw_do,
417 spw_so => spw_so );
418 end generate;
419 xmit_sel1: if tximpl = impl_fast generate
420 xmit_fast_inst: spwxmit_fast
421 port map (
422 clk => clk,
423 txclk => txclk,
424 rst => xmit_rst,
425 divcnt => xmit_divcnt,
426 xmiti => xmiti,
427 xmito => xmito,
428 spw_do => spw_do,
429 spw_so => spw_so );
430 end generate;
431
432 -- Instantiate RX FIFO.
433 rxfifo: syncram_2p
434 generic map (
435 tech => tech,
436 abits => rxfifosize,
437 dbits => 36,
438 sepclk => 0 )
439 port map (
440 rclk => clk,
441 renable => '1',
442 raddress => s_rxfifo_raddr,
443 dataout => s_rxfifo_rdata,
444 wclk => clk,
445 write => s_rxfifo_wen,
446 waddress => s_rxfifo_waddr,
447 datain => s_rxfifo_wdata );
448
449 -- Instantiate TX FIFO.
450 txfifo: syncram_2p
451 generic map (
452 tech => tech,
453 abits => txfifosize,
454 dbits => 36,
455 sepclk => 0 )
456 port map (
457 rclk => clk,
458 renable => '1',
459 raddress => s_txfifo_raddr,
460 dataout => s_txfifo_rdata,
461 wclk => clk,
462 write => s_txfifo_wen,
463 waddress => s_txfifo_waddr,
464 datain => s_txfifo_wdata );
465
466 -- Instantiate AHB master.
467 ahbmst: spwahbmst
468 generic map (
469 hindex => hindex,
470 hconfig => hconfig,
471 maxburst => maxburst )
472 port map (
473 clk => clk,
474 rstn => ahbmst_rstn,
475 msti => msti,
476 msto => msto,
477 ahbi => ahbi,
478 ahbo => ahbo );
479
480
481 --
482 -- Combinatorial process
483 --
484 process (r, linko, msto, s_rxfifo_rdata, s_txfifo_rdata, rstn, apbi, tick_in) is
485 variable v: regs_type;
486 variable v_tmprxroom: unsigned(rxfifosize-1 downto 0);
487 variable v_prdata: std_logic_vector(31 downto 0);
488 variable v_irq: std_logic_vector(NAHBIRQ-1 downto 0);
489 variable v_txfifo_bytepos: integer range 0 to 3;
490 begin
491 v := r;
492 v_tmprxroom := to_unsigned(0, rxfifosize);
493 v_prdata := (others => '0');
494 v_irq := (others => '0');
495 v_irq(pirq) := r.irq;
496
497 -- Convert RX/TX byte index to integer.
498 v_txfifo_bytepos := to_integer(unsigned(r.txfifo_bytepos));
499
500 -- Reset auto-clearing registers.
501 v.ctl_reset := '0';
502 v.ctl_resetdma := '0';
503 v.ctl_rxstart := '0';
504 v.ctl_txstart := '0';
505
506 -- Register external timecode trigger (if enabled).
507 if timecodegen and r.ctl_ticken = '1' then
508 v.tick_in := tick_in;
509 else
510 v.tick_in := '0';
511 end if;
512
513 -- Auto-increment timecode counter.
514 if r.tick_in = '1' then
515 v.time_in := std_logic_vector(unsigned(r.time_in) + 1);
516 end if;
517
518 -- Keep track of whether we are sending and/or receiving a packet.
519 if linko.rxchar = '1' then
520 -- got character
521 v.rxpacket := not linko.rxflag;
522 end if;
523 if linko.txack = '1' then
524 -- send character
525 v.txpacket := not s_txfifo_rdata(35-v_txfifo_bytepos);
526 end if;
527
528 -- Accumulate a word to write to the RX fifo.
529 -- Note: If the EOP/EEP marker falls in the middle of a word,
530 -- subsequent bytes must be a copy of the marker, otherwise
531 -- the AHB master may not work correctly.
532 v.rxfifo_write := '0';
533 for i in 3 downto 0 loop
534 if (i = 0) or (r.rxfifo_bytemsk(i-1) = '1') then
535 if r.rxeep = '1' then
536 v.rxfifo_wdata(32+i) := '1';
537 v.rxfifo_wdata(7+8*i downto 8*i) := "00000001";
538 else
539 v.rxfifo_wdata(32+i) := linko.rxflag;
540 v.rxfifo_wdata(7+8*i downto 8*i) := linko.rxdata;
541 end if;
542 end if;
543 end loop;
544 if linko.rxchar = '1' or (r.rxeep = '1' and unsigned(r.rxroom) /= 0) then
545 v.rxeep := '0';
546 if r.rxfifo_bytemsk(0) = '0' or linko.rxflag = '1' or r.rxeep = '1' then
547 -- Flush the current word to the FIFO.
548 v.rxfifo_write := '1';
549 v.rxfifo_bytemsk := "111";
550 else
551 -- Store one byte.
552 v.rxfifo_bytemsk := '0' & r.rxfifo_bytemsk(2 downto 1);
553 end if;
554 end if;
555
556 -- Read from TX fifo.
557 if (r.txfifo_empty = '0') and (linko.txack = '1' or r.txdiscard = '1') then
558 -- Update byte pointer.
559 if r.txfifo_bytepos = "11" or
560 s_txfifo_rdata(35-v_txfifo_bytepos) = '1' or
561 (v_txfifo_bytepos < 3 and
562 s_txfifo_rdata(34-v_txfifo_bytepos) = '1' and
563 s_txfifo_rdata(23-8*v_txfifo_bytepos) = '1') then
564 -- This is the last byte in the current word;
565 -- OR the current byte is an EOP/EEP marker;
566 -- OR the next byte in the current word is a non-EOP end-of-frame marker.
567 v.txfifo_bytepos := "00";
568 v.txfifo_raddr := std_logic_vector(unsigned(r.txfifo_raddr) + 1);
569 else
570 -- Move to next byte.
571 v.txfifo_bytepos := std_logic_vector(unsigned(r.txfifo_bytepos) + 1);
572 end if;
573 -- Clear discard flag when past EOP.
574 if s_txfifo_rdata(35-v_txfifo_bytepos) = '1' then
575 v.txdiscard := '0';
576 end if;
577 end if;
578
579 -- Update RX fifo pointers.
580 if msto.rxfifo_read = '1' then
581 -- Read one word.
582 v.rxfifo_raddr := std_logic_vector(unsigned(r.rxfifo_raddr) + 1);
583 end if;
584 if r.rxfifo_write = '1' then
585 -- Write one word.
586 v.rxfifo_waddr := std_logic_vector(unsigned(r.rxfifo_waddr) + 1);
587 end if;
588
589 -- Detect RX fifo empty (using new value of rxfifo_raddr).
590 -- Note: The FIFO is empty if head and tail pointer are equal.
591 v.rxfifo_empty := conv_std_logic(v.rxfifo_raddr = r.rxfifo_waddr);
592
593 -- Indicate RX fifo room for SpaceWire flow control.
594 -- The flow control window is normally expressed as a number of bytes,
595 -- but we don't know how many bytes we can fit in each word because
596 -- some words are only partially used. So we report FIFO room as if
597 -- each FIFO word can hold only one byte, which is an overly
598 -- pessimistic estimate.
599 -- (Use the new value of rxfifo_waddr.)
600 v_tmprxroom := unsigned(r.rxfifo_raddr) - unsigned(v.rxfifo_waddr) - 1;
601 if v_tmprxroom > 63 then
602 -- at least 64 bytes room.
603 v.rxroom := "111111";
604 else
605 -- less than 64 bytes room.
606 -- If linko.rxchar = '1', decrease rxroom by one to account for
607 -- the pipeline delay through r.rxfifo_write.
608 v.rxroom := std_logic_vector(v_tmprxroom(5 downto 0) -
609 to_unsigned(conv_integer(linko.rxchar), 6));
610 end if;
611
612 -- Update TX fifo write pointer.
613 if msto.txfifo_write = '1' then
614 -- write one word.
615 v.txfifo_waddr := std_logic_vector(unsigned(r.txfifo_waddr) + 1);
616 end if;
617
618 -- Detect TX fifo empty.
619 -- Note: The FIFO may be either full or empty if head and tail pointer
620 -- are equal, hence the additional test for txfifo_nxfull.
621 v.txfifo_empty := conv_std_logic(v.txfifo_raddr = r.txfifo_waddr) and not r.txfifo_nxfull;
622
623 -- Detect TX fifo full after one more write.
624 if unsigned(r.txfifo_raddr) - unsigned(r.txfifo_waddr) = to_unsigned(2, txfifosize) then
625 -- currently exactly 2 words left.
626 v.txfifo_nxfull := msto.txfifo_write;
627 end if;
628
629 -- Detect TX fifo high water mark.
630 if txfifosize > maxburst then
631 -- Indicate high water when there is no room for a maximum burst.
632 if unsigned(r.txfifo_raddr) - unsigned(r.txfifo_waddr) = to_unsigned(2**maxburst + 1, txfifosize) then
633 -- currently room for exactly one maximum burst.
634 v.txfifo_highw := msto.txfifo_write;
635 end if;
636 else
637 -- Indicate high water when more than half full.
638 if unsigned(r.txfifo_raddr) - unsigned(r.txfifo_waddr) = to_unsigned(2**(txfifosize-1), txfifosize) then
639 -- currently exactly half full.
640 v.txfifo_highw := msto.txfifo_write;
641 end if;
642 end if;
643
644 -- Update descriptor pointers.
645 if msto.rxdesc_next = '1' then
646 if msto.rxdesc_wrap = '1' then
647 v.rxdesc_ptr(desctablesize+2 downto 3) := (others => '0');
648 else
649 v.rxdesc_ptr(desctablesize+2 downto 3) :=
650 std_logic_vector(unsigned(r.rxdesc_ptr(desctablesize+2 downto 3)) + 1);
651 end if;
652 end if;
653 if msto.txdesc_next = '1' then
654 if msto.txdesc_wrap = '1' then
655 v.txdesc_ptr(desctablesize+2 downto 3) := (others => '0');
656 else
657 v.txdesc_ptr(desctablesize+2 downto 3) :=
658 std_logic_vector(unsigned(r.txdesc_ptr(desctablesize+2 downto 3)) + 1);
659 end if;
660 end if;
661
662 -- If the link is lost, set a flag to discard the current packet.
663 if linko.running = '0' then
664 v.rxeep := v.rxeep or v.rxpacket; -- use new value of rxpacket
665 v.txdiscard := v.txdiscard or v.txpacket; -- use new value of txpacket
666 v.rxpacket := '0';
667 v.txpacket := '0';
668 end if;
669
670 -- Clear the discard flag when the link is explicitly disabled.
671 if r.ctl_linkdis = '1' then
672 v.txdiscard := '0';
673 end if;
674
675 -- Extend TX cancel command until TX DMA has stopped.
676 if msto.txdma_act = '0' then
677 v.ctl_txcancel := '0';
678 end if;
679
680 -- Update status registers.
681 v.sta_link(0) := linko.running or linko.started;
682 v.sta_link(1) := linko.running or linko.connecting;
683 if linko.errdisc = '1' then v.sta_errdisc := '1'; end if;
684 if linko.errpar = '1' then v.sta_errpar := '1'; end if;
685 if linko.erresc = '1' then v.sta_erresc := '1'; end if;
686 if linko.errcred = '1' then v.sta_errcred := '1'; end if;
687 if linko.tick_out = '1' then v.sta_gottick := '1'; end if;
688 if msto.int_rxdesc = '1' then v.sta_rxdesc := '1'; end if;
689 if msto.int_txdesc = '1' then v.sta_txdesc := '1'; end if;
690 if msto.int_rxpacket = '1' then v.sta_rxpacket := '1'; end if;
691 if msto.int_rxpacket = '1' and r.rxfifo_empty = '1' then
692 v.sta_rxempty := '1';
693 elsif r.rxfifo_empty = '0' then
694 v.sta_rxempty := '0';
695 end if;
696
697 -- Generate interrupt requests.
698 v.irq :=
699 (r.ctl_ielink and (linko.running xor (r.sta_link(0) and r.sta_link(1)))) or
700 (r.ctl_ietick and linko.tick_out) or
701 (r.ctl_ierxdesc and msto.int_rxdesc) or
702 (r.ctl_ietxdesc and msto.int_txdesc) or
703 (r.ctl_ierxpacket and msto.int_rxpacket);
704
705 -- APB read access.
706 if apbi.psel(pindex) = '1' then
707 case apbi.paddr(4 downto 2) is
708 when "000" => -- read control register
709 v_prdata(0) := '0';
710 v_prdata(1) := '0';
711 v_prdata(2) := r.ctl_linkstart;
712 v_prdata(3) := r.ctl_autostart;
713 v_prdata(4) := r.ctl_linkdis;
714 v_prdata(5) := r.ctl_ticken;
715 v_prdata(6) := '0';
716 v_prdata(7) := '0';
717 v_prdata(8) := r.ctl_txcancel;
718 v_prdata(9) := r.ctl_ielink;
719 v_prdata(10) := r.ctl_ietick;
720 v_prdata(11) := r.ctl_ierxdesc;
721 v_prdata(12) := r.ctl_ietxdesc;
722 v_prdata(13) := r.ctl_ierxpacket;
723 v_prdata(27 downto 24) := std_logic_vector(to_unsigned(desctablesize, 4));
724 when "001" => -- read status register
725 v_prdata(1 downto 0) := r.sta_link;
726 v_prdata(2) := r.sta_errdisc;
727 v_prdata(3) := r.sta_errpar;
728 v_prdata(4) := r.sta_erresc;
729 v_prdata(5) := r.sta_errcred;
730 v_prdata(6) := msto.rxdma_act;
731 v_prdata(7) := msto.txdma_act;
732 v_prdata(8) := msto.ahberror;
733 v_prdata(10) := r.sta_gottick;
734 v_prdata(11) := r.sta_rxdesc;
735 v_prdata(12) := r.sta_txdesc;
736 v_prdata(13) := r.sta_rxpacket;
737 v_prdata(14) := r.sta_rxempty;
738 when "010" => -- read transmission clock scaler
739 v_prdata(7 downto 0) := r.txdivcnt;
740 when "011" => -- read timecode register
741 v_prdata(5 downto 0) := linko.time_out;
742 v_prdata(7 downto 6) := linko.ctrl_out;
743 v_prdata(13 downto 8) := r.time_in;
744 v_prdata(16 downto 14) := "000";
745 when "100" => -- read rx descriptor pointer
746 v_prdata(2 downto 0) := (others => '0');
747 v_prdata(31 downto 3) := r.rxdesc_ptr;
748 when "101" => -- read tx descriptor pointer
749 v_prdata(2 downto 0) := (others => '0');
750 v_prdata(31 downto 3) := r.txdesc_ptr;
751 when others =>
752 null;
753 end case;
754 end if;
755
756 -- APB write access.
757 if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
758 case apbi.paddr(4 downto 2) is
759 when "000" => -- write control register
760 v.ctl_reset := apbi.pwdata(0);
761 v.ctl_resetdma := apbi.pwdata(1);
762 v.ctl_linkstart := apbi.pwdata(2);
763 v.ctl_autostart := apbi.pwdata(3);
764 v.ctl_linkdis := apbi.pwdata(4);
765 v.ctl_ticken := apbi.pwdata(5);
766 v.ctl_rxstart := apbi.pwdata(6);
767 v.ctl_txstart := apbi.pwdata(7);
768 if apbi.pwdata(8) = '1' then v.ctl_txcancel := '1'; end if;
769 v.ctl_ielink := apbi.pwdata(9);
770 v.ctl_ietick := apbi.pwdata(10);
771 v.ctl_ierxdesc := apbi.pwdata(11);
772 v.ctl_ietxdesc := apbi.pwdata(12);
773 v.ctl_ierxpacket := apbi.pwdata(13);
774 when "001" => -- write status register
775 if apbi.pwdata(2) = '1' then v.sta_errdisc := '0'; end if;
776 if apbi.pwdata(3) = '1' then v.sta_errpar := '0'; end if;
777 if apbi.pwdata(4) = '1' then v.sta_erresc := '0'; end if;
778 if apbi.pwdata(5) = '1' then v.sta_errcred := '0'; end if;
779 if apbi.pwdata(10) = '1' then v.sta_gottick := '0'; end if;
780 if apbi.pwdata(11) = '1' then v.sta_rxdesc := '0'; end if;
781 if apbi.pwdata(12) = '1' then v.sta_txdesc := '0'; end if;
782 if apbi.pwdata(13) = '1' then v.sta_rxpacket := '0'; end if;
783 when "010" => -- write transmission clock scaler
784 v.txdivcnt := apbi.pwdata(7 downto 0);
785 when "011" => -- write timecode register
786 v.time_in := apbi.pwdata(13 downto 8);
787 if apbi.pwdata(16) = '1' then v.tick_in := '1'; end if;
788 when "100" => -- write rx descriptor pointer
789 v.rxdesc_ptr := apbi.pwdata(31 downto 3);
790 when "101" => -- write tx descriptor pointer
791 v.txdesc_ptr := apbi.pwdata(31 downto 3);
792 when others =>
793 null;
794 end case;
795 end if;
796
797 -- Drive control signals to RX fifo.
798 s_rxfifo_raddr <= v.rxfifo_raddr; -- new value of rxfifo_raddr
799 s_rxfifo_wen <= r.rxfifo_write;
800 s_rxfifo_waddr <= r.rxfifo_waddr;
801 s_rxfifo_wdata <= r.rxfifo_wdata;
802
803 -- Drive control signals to TX fifo.
804 s_txfifo_raddr <= v.txfifo_raddr; -- new value of txfifo_raddr
805 s_txfifo_wen <= msto.txfifo_write;
806 s_txfifo_waddr <= r.txfifo_waddr;
807 s_txfifo_wdata <= msto.txfifo_wdata;
808
809 -- Drive inputs to spwlink.
810 linki.autostart <= r.ctl_autostart;
811 linki.linkstart <= r.ctl_linkstart;
812 linki.linkdis <= r.ctl_linkdis;
813 linki.rxroom <= r.rxroom;
814 linki.tick_in <= r.tick_in;
815 linki.ctrl_in <= "00";
816 linki.time_in <= r.time_in;
817 linki.txwrite <= (not r.txfifo_empty) and (not r.txdiscard);
818 linki.txflag <= s_txfifo_rdata(35-v_txfifo_bytepos);
819 linki.txdata <= s_txfifo_rdata(31-8*v_txfifo_bytepos downto 24-8*v_txfifo_bytepos);
820
821 -- Drive divcnt input to spwxmit.
822 if linko.running = '1' then
823 xmit_divcnt <= r.txdivcnt;
824 else
825 xmit_divcnt <= default_divcnt;
826 end if;
827
828 -- Drive inputs to AHB master.
829 msti.rxdma_start <= r.ctl_rxstart;
830 msti.txdma_start <= r.ctl_txstart;
831 msti.txdma_cancel <= r.ctl_txcancel;
832 msti.rxdesc_ptr <= r.rxdesc_ptr;
833 msti.txdesc_ptr <= r.txdesc_ptr;
834 msti.rxfifo_rdata <= s_rxfifo_rdata;
835 msti.rxfifo_empty <= r.rxfifo_empty;
836 msti.rxfifo_nxempty <= v.rxfifo_empty; -- new value of rxfifo_empty
837 msti.txfifo_nxfull <= r.txfifo_nxfull;
838 msti.txfifo_highw <= r.txfifo_highw;
839
840 -- Pass tick_out signal to output port.
841 tick_out <= linko.tick_out;
842
843 -- Drive APB output signals.
844 apbo.prdata <= v_prdata;
845 apbo.pirq <= v_irq;
846 apbo.pconfig <= pconfig;
847 apbo.pindex <= pindex;
848
849 -- Reset components.
850 ahbmst_rstn <= rstn and (not r.ctl_reset) and (not r.ctl_resetdma);
851 link_rst <= (not rstn) or r.ctl_reset;
852 xmit_rst <= not rstn;
853
854 -- Clear TX fifo on cancel request.
855 if r.ctl_txcancel = '1' then
856 v.txfifo_raddr := (others => '0');
857 v.txfifo_waddr := (others => '0');
858 v.txfifo_empty := '1';
859 v.txfifo_nxfull := '0';
860 v.txfifo_highw := '0';
861 v.txfifo_bytepos := "00";
862 v.txpacket := '0';
863 v.txdiscard := '0';
864 end if;
865
866 -- Reset registers.
867 if rstn = '0' or r.ctl_reset = '1' then
868 v := regs_reset;
869 end if;
870
871 -- Update registers.
872 rin <= v;
873 end process;
874
875
876 --
877 -- Update registers.
878 --
879 process (clk) is
880 begin
881 if rising_edge(clk) then
882 r <= rin;
883 end if;
884 end process;
885
886 end architecture spwamba_arch;
@@ -0,0 +1,159
1 --
2 -- VHDL package for SpaceWire AMBA interface.
3 --
4 -- This package depends on Gaisler GRLIB.
5 --
6
7 library ieee;
8 use ieee.std_logic_1164.all;
9 library grlib;
10 use grlib.amba.all;
11 library techmap;
12 use techmap.gencomp.all;
13 use work.spwpkg.all;
14
15 package spwambapkg is
16
17
18 -- AMBA plug&play device id
19 constant DEVICE_SPACEWIRELIGHT: amba_device_type := 16#131#;
20
21
22 -- Signals from SpaceWire core to AHB master.
23 type spw_ahbmst_in_type is record
24
25 -- Pulse high to start the RX DMA engine.
26 rxdma_start: std_ulogic;
27
28 -- Pulse high to start the TX DMA engine.
29 txdma_start: std_ulogic;
30
31 -- Stop TX DMA engine (at end of current burst).
32 txdma_cancel: std_ulogic;
33
34 -- Address of current RX descriptor (8-byte aligned).
35 rxdesc_ptr: std_logic_vector(31 downto 3);
36
37 -- Address of current TX descriptor (8-byte aligned).
38 txdesc_ptr: std_logic_vector(31 downto 3);
39
40 -- Read port of RX FIFO.
41 rxfifo_rdata: std_logic_vector(35 downto 0);
42
43 -- High if RX FIFO is empty.
44 rxfifo_empty: std_ulogic;
45
46 -- High if RX FIFO will be empty after one read.
47 -- May combinatorially depend on spw_ahbmst_out_type.rxfifo_read.
48 rxfifo_nxempty: std_ulogic;
49
50 -- High if TX FIFO is full or has room for at most one word.
51 txfifo_nxfull: std_ulogic;
52
53 -- High if TX FIFO is close to full (blocks refill).
54 txfifo_highw: std_ulogic;
55 end record;
56
57 -- Signals from AHB master to SpaceWire core.
58 type spw_ahbmst_out_type is record
59
60 -- High if the RX DMA engine is enabled.
61 rxdma_act: std_ulogic;
62
63 -- High if the TX DMA engine is enabled.
64 txdma_act: std_ulogic;
65
66 -- High if an error occurred on the AHB bus.
67 ahberror: std_ulogic;
68
69 -- Pulsed high to trigger an RX descriptor interrupt.
70 int_rxdesc: std_ulogic;
71
72 -- Pulsed high to trigger a TX descriptor interrupt.
73 int_txdesc: std_ulogic;
74
75 -- Pulsed high when a complete packet has been received.
76 int_rxpacket: std_ulogic;
77
78 -- Pulsed high to request the next RX descriptor address.
79 -- (rxdesc_ptr must be updated in the next clock cycle).
80 rxdesc_next: std_ulogic;
81
82 -- Pulsed high together with rxdesc_next to wrap the RX descriptor pointer.
83 rxdesc_wrap: std_ulogic;
84
85 -- Pulsed high to request the next TX descriptor address.
86 -- (txdesc_ptr must be updated in the next clock cycle).
87 txdesc_next: std_ulogic;
88
89 -- Pulsed high together with txdesc_next to wrap the TX descriptor pointer.
90 txdesc_wrap: std_ulogic;
91
92 -- Read strobe to RX fifo.
93 rxfifo_read: std_ulogic;
94
95 -- Write enable to TX fifo.
96 txfifo_write: std_ulogic;
97
98 -- Input port of TX fifo.
99 txfifo_wdata: std_logic_vector(35 downto 0);
100 end record;
101
102
103 -- SpaceWire core with AMBA interface.
104 component spwamba is
105 generic (
106 tech: integer range 0 to NTECH := DEFFABTECH;
107 hindex: integer; -- AHB master index
108 pindex: integer; -- APB slave index
109 paddr: integer; -- APB address range
110 pmask: integer := 16#fff#; -- APB address mask
111 pirq: integer; -- interrupt number
112 sysfreq: real; -- system clock frequency in Hz
113 txclkfreq: real := 0.0; -- txclk frequency in Hz
114 rximpl: spw_implementation_type := impl_generic;
115 rxchunk: integer range 1 to 4 := 1;
116 tximpl: spw_implementation_type := impl_generic;
117 timecodegen: boolean := true; -- support timecode generation
118 rxfifosize: integer range 6 to 12 := 8; -- size of receive FIFO (2-log of words)
119 txfifosize: integer range 2 to 12 := 8; -- size of transmit FIFO (2-log of words)
120 desctablesize: integer range 4 to 14 := 10; -- size of the DMA descriptor tables (2-log of descriptors)
121 maxburst: integer range 1 to 8 := 3 -- max burst length (2-log of words)
122 );
123 port (
124 clk: in std_logic; -- system clock.
125 rxclk: in std_logic; -- receiver sample clock
126 txclk: in std_logic; -- transmit clock
127 rstn: in std_logic; -- synchronous reset (active-low)
128 apbi: in apb_slv_in_type; -- APB slave input signals
129 apbo: out apb_slv_out_type; -- APB slave output signals
130 ahbi: in ahb_mst_in_type; -- AHB master input signals
131 ahbo: out ahb_mst_out_type; -- AHB master output signals
132 tick_in: in std_logic; -- pulse for timecode generation
133 tick_out: out std_logic; -- timecode received
134 spw_di: in std_logic; -- Data In signal from SpaceWire bus
135 spw_si: in std_logic; -- Strobe In signal from SpaceWire bus
136 spw_do: out std_logic; -- Data Out signal to SpaceWire bus
137 spw_so: out std_logic -- Strobe Out signal to SpaceWire bus
138 );
139 end component spwamba;
140
141
142 -- AHB master for AMBA interface.
143 component spwahbmst is
144 generic (
145 hindex: integer; -- AHB master index
146 hconfig: ahb_config_type; -- AHB plug&play information
147 maxburst: integer range 1 to 8 -- 2log of max burst length
148 );
149 port (
150 clk: in std_logic; -- system clock
151 rstn: in std_logic; -- synchronous reset (active-low)
152 msti: in spw_ahbmst_in_type; -- inputs from SpaceWire core
153 msto: out spw_ahbmst_out_type; -- outputs to SpaceWire core
154 ahbi: in ahb_mst_in_type; -- AHB master input signals
155 ahbo: out ahb_mst_out_type -- AHB master output signals
156 );
157 end component spwahbmst;
158
159 end package;
@@ -0,0 +1,286
1 --
2 -- SpaceWire Exchange Level Controller.
3 --
4 -- This entity implements exchange level aspects of the SpaceWire protocol.
5 -- It handles connection setup, error detection and flow control.
6 --
7
8 library ieee;
9 use ieee.std_logic_1164.all;
10 use ieee.numeric_std.all;
11 use work.spwpkg.all;
12
13 entity spwlink is
14
15 generic (
16 -- Reset time expressed in system clock cycles.
17 -- Should be 6.4 us (5.82 us .. 7.2 us) according to the standard.
18 reset_time: integer
19 );
20
21 port (
22 -- System clock.
23 clk: in std_logic;
24
25 -- Synchronous reset (active-high).
26 -- Disconnects, resets error conditions, puts the link state machine
27 -- in state ErrorReset.
28 rst: in std_logic;
29
30 -- Link level inputs.
31 linki: in spw_link_in_type;
32
33 -- Link level outputs.
34 linko: out spw_link_out_type;
35
36 -- Receiver enable signal to spwrecv.
37 rxen: out std_logic;
38
39 -- Output signals from spwrecv.
40 recvo: in spw_recv_out_type;
41
42 -- Input signals for spwxmit.
43 xmiti: out spw_xmit_in_type;
44
45 -- Output signals from spwxmit.
46 xmito: in spw_xmit_out_type
47 );
48
49 end entity spwlink;
50
51 architecture spwlink_arch of spwlink is
52
53 -- Convert boolean to std_logic.
54 type bool_to_logic_type is array(boolean) of std_ulogic;
55 constant bool_to_logic: bool_to_logic_type := (false => '0', true => '1');
56
57 -- State machine.
58 type state_type is (
59 S_ErrorReset, S_ErrorWait, S_Ready, S_Started, S_Connecting, S_Run );
60
61 -- Registers
62 type regs_type is record
63 -- state machine
64 state: state_type;
65 -- credit accounting
66 tx_credit: unsigned(5 downto 0);
67 rx_credit: unsigned(5 downto 0);
68 errcred: std_ulogic;
69 -- reset timer
70 timercnt: unsigned(10 downto 0);
71 timerdone: std_ulogic;
72 -- signal to transmitter
73 xmit_fct_in: std_ulogic;
74 end record;
75
76 -- Initial state
77 constant regs_reset: regs_type := (
78 state => S_ErrorReset,
79 tx_credit => "000000",
80 rx_credit => "000000",
81 errcred => '0',
82 timercnt => to_unsigned(reset_time, 11),
83 timerdone => '0',
84 xmit_fct_in => '0' );
85
86 signal r: regs_type := regs_reset;
87 signal rin: regs_type;
88
89 begin
90
91 -- Combinatorial process
92 process (r, rst, linki, recvo, xmito) is
93 variable v: regs_type;
94 variable v_timerrst: std_logic;
95 begin
96 v := r;
97 v_timerrst := '0';
98
99 -- State machine.
100 case r.state is
101
102 when S_ErrorReset =>
103 -- Wait for timer.
104 if r.timercnt = 0 then
105 v.state := S_ErrorWait;
106 v_timerrst := '1';
107 end if;
108 v.errcred := '0';
109 v.xmit_fct_in := '0';
110
111 when S_ErrorWait =>
112 -- Wait for 2 timer periods.
113 if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
114 ((recvo.gotfct or recvo.tick_out or recvo.rxchar) = '1') then
115 -- Note: spwrecv will never issue errpar, erresc, gotfct,
116 -- tick_out or rxchar before the first NULL has been seen.
117 -- Therefore it's ok here to bail on those conditions
118 -- without explicitly testing got_null.
119 v.state := S_ErrorReset; -- error, go back to reset
120 v_timerrst := '1';
121 elsif r.timercnt = 0 then
122 if r.timerdone = '1' then
123 v.state := S_Ready;
124 v_timerrst := '1';
125 end if;
126 end if;
127
128 when S_Ready =>
129 -- Wait for link start.
130 if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
131 ((recvo.gotfct or recvo.tick_out or recvo.rxchar) = '1') then
132 v.state := S_ErrorReset; -- error, go back to reset
133 v_timerrst := '1';
134 elsif (linki.linkdis = '0') and (r.xmit_fct_in = '1') and
135 ((linki.linkstart or (linki.autostart and recvo.gotnull)) = '1') then
136 v.state := S_Started; -- link enabled; start sending NULL
137 v_timerrst := '1';
138 end if;
139
140 when S_Started =>
141 -- Wait for NULL.
142 if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
143 ((recvo.gotfct or recvo.tick_out or recvo.rxchar) = '1') or
144 ((r.timercnt = 0) and r.timerdone = '1') then
145 v.state := S_ErrorReset; -- error, go back to reset
146 v_timerrst := '1';
147 elsif recvo.gotnull = '1' then
148 v.state := S_Connecting; -- received null, continue
149 v_timerrst := '1';
150 end if;
151
152 when S_Connecting =>
153 -- Wait for FCT.
154 if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
155 ((recvo.tick_out or recvo.rxchar) = '1') or
156 ((r.timercnt = 0) and r.timerdone = '1') then
157 v.state := S_ErrorReset; -- error, go back to reset
158 v_timerrst := '1';
159 elsif recvo.gotfct = '1' then
160 v.state := S_Run; -- got FCT, init completed
161 end if;
162
163 when S_Run =>
164 -- All is well.
165 if ((recvo.errdisc or recvo.errpar or recvo.erresc) = '1') or
166 (r.errcred = '1') or
167 (linki.linkdis = '1') then
168 v.state := S_ErrorReset; -- error, go back to reset
169 v_timerrst := '1';
170 end if;
171
172 when others =>
173 v.state := S_ErrorReset; -- recover from invalid state
174 v_timerrst := '1';
175
176 end case;
177
178 -- Update credit counters.
179 if r.state = S_ErrorReset then
180
181 -- reset credit
182 v.tx_credit := to_unsigned(0, v.tx_credit'length);
183 v.rx_credit := to_unsigned(0, v.rx_credit'length);
184
185 else
186
187 -- update TX credit
188 if recvo.gotfct = '1' then
189 -- just received a FCT token
190 v.tx_credit := v.tx_credit + to_unsigned(8, v.tx_credit'length);
191 if r.tx_credit > 48 then
192 -- received too many FCT tokens
193 v.errcred := '1';
194 end if;
195 end if;
196 if xmito.txack = '1' then
197 -- just sent one byte
198 v.tx_credit := v.tx_credit - to_unsigned(1, v.tx_credit'length);
199 end if;
200
201 -- update RX credit after sending FCT
202 if xmito.fctack = '1' then
203 -- just sent a FCT token
204 v.rx_credit := v.rx_credit + to_unsigned(8, v.rx_credit'length);
205 end if;
206
207 -- decide about sending FCT tokens
208 v.xmit_fct_in := bool_to_logic( (v.rx_credit <= 48) and
209 (v.rx_credit + to_unsigned(8, v.rx_credit'length) <= unsigned(linki.rxroom)) );
210
211 -- update RX credit after receiving character
212 if recvo.rxchar = '1' then
213 -- just received a character
214 v.rx_credit := v.rx_credit - to_unsigned(1, v.rx_credit'length);
215 if r.rx_credit = 0 then
216 -- remote transmitter violated its credit
217 v.errcred := '1';
218 end if;
219 end if;
220
221 end if;
222
223 -- Update the initializaton reset timer.
224 if v_timerrst = '1' then
225 v.timercnt := to_unsigned(reset_time, v.timercnt'length);
226 v.timerdone := '0';
227 else
228 if r.timercnt = 0 then
229 v.timercnt := to_unsigned(reset_time, v.timercnt'length);
230 v.timerdone := '1';
231 else
232 v.timercnt := r.timercnt - 1;
233 end if;
234 end if;
235
236 -- Reset
237 if rst = '1' then
238 v := regs_reset;
239 end if;
240
241 -- Drive link level outputs.
242 linko.started <= bool_to_logic(r.state = S_Started);
243 linko.connecting <= bool_to_logic(r.state = S_Connecting);
244 linko.running <= bool_to_logic(r.state = S_Run);
245 linko.errdisc <= recvo.errdisc and bool_to_logic(r.state = S_Run);
246 linko.errpar <= recvo.errpar and bool_to_logic(r.state = S_Run);
247 linko.erresc <= recvo.erresc and bool_to_logic(r.state = S_Run);
248 linko.errcred <= r.errcred;
249 linko.txack <= xmito.txack;
250 linko.tick_out <= recvo.tick_out and bool_to_logic(r.state = S_Run);
251 linko.ctrl_out <= recvo.ctrl_out;
252 linko.time_out <= recvo.time_out;
253 linko.rxchar <= recvo.rxchar and bool_to_logic(r.state = S_Run);
254 linko.rxflag <= recvo.rxflag;
255 linko.rxdata <= recvo.rxdata;
256
257 -- Drive receiver inputs.
258 rxen <= bool_to_logic(r.state /= S_ErrorReset);
259
260 -- Drive transmitter input signals.
261 xmiti.txen <= bool_to_logic(r.state = S_Started or
262 r.state = S_Connecting or
263 r.state = S_Run);
264 xmiti.stnull <= bool_to_logic(r.state = S_Started);
265 xmiti.stfct <= bool_to_logic(r.state = S_Connecting);
266 xmiti.fct_in <= r.xmit_fct_in;
267 xmiti.tick_in <= linki.tick_in and bool_to_logic(r.state = S_Run);
268 xmiti.ctrl_in <= linki.ctrl_in;
269 xmiti.time_in <= linki.time_in;
270 xmiti.txwrite <= linki.txwrite and bool_to_logic(r.tx_credit /= 0);
271 xmiti.txflag <= linki.txflag;
272 xmiti.txdata <= linki.txdata;
273
274 -- Update registers.
275 rin <= v;
276 end process;
277
278 -- Update registers.
279 process (clk) is
280 begin
281 if rising_edge(clk) then
282 r <= rin;
283 end if;
284 end process;
285
286 end architecture spwlink_arch;
@@ -0,0 +1,403
1 --
2 -- SpaceWire VHDL package
3 --
4
5 library ieee;
6 use ieee.std_logic_1164.all;
7
8 package spwpkg is
9
10
11 -- Indicates a platform-specific implementation.
12 type spw_implementation_type is ( impl_generic, impl_fast );
13
14
15 -- Input signals to spwlink.
16 type spw_link_in_type is record
17
18 -- Enables automatic link start on receipt of a NULL character.
19 autostart: std_logic;
20
21 -- Enables link start once the Ready state is reached.
22 -- Without either "autostart" or "linkstart", the link remains in
23 -- state Ready.
24 linkstart: std_logic;
25
26 -- Do not start link (overrides "linkstart" and "autostart") and/or
27 -- disconnect the currently running link.
28 linkdis: std_logic;
29
30 -- Number of bytes available in the receive buffer. Used to for
31 -- flow-control operation. At least 8 bytes must be available
32 -- initially, otherwise the link can not start. Values larger than 63
33 -- are irrelevant and may be presented as 63. The available room may
34 -- decrease by one byte due to the reception of an N-Char; in that case
35 -- the "rxroom" signal must be updated on the clock following the clock
36 -- on which "rxchar" is high. Under no other circumstances may "rxroom"
37 -- be decreased.
38 rxroom: std_logic_vector(5 downto 0);
39
40 -- High for one clock cycle to request transmission of a TimeCode.
41 -- The request is registered inside spwxmit until it can be processed.
42 tick_in: std_logic;
43
44 -- Control bits of the TimeCode to be sent.
45 -- Must be valid while tick_in is high.
46 ctrl_in: std_logic_vector(1 downto 0);
47
48 -- Counter value of the TimeCode to be sent.
49 -- Must be valid while tick_in is high.
50 time_in: std_logic_vector(5 downto 0);
51
52 -- Requests transmission of an N-Char.
53 -- Keep this signal high until confirmed by "txack".
54 txwrite: std_logic;
55
56 -- Control flag to be sent with the next N-Char.
57 -- Must be valid while "txwrite" is high.
58 txflag: std_logic;
59
60 -- Byte to be sent, or "00000000" for EOP or "00000001" for EEP.
61 -- Must be valid while "txwrite" is high.
62 txdata: std_logic_vector(7 downto 0);
63 end record;
64
65
66 -- Output signals from spwlink.
67 type spw_link_out_type is record
68
69 -- High if the link state machine is currently in state Started.
70 started: std_logic;
71
72 -- High if the link state machine is currently in state Connecting.
73 connecting: std_logic;
74
75 -- High if the link state machine is currently in state Run.
76 running: std_logic;
77
78 -- Disconnect detected in state Run. Triggers a reset and reconnect.
79 -- This indication is auto-clearing.
80 errdisc: std_logic;
81
82 -- Parity error detected in state Run. Triggers a reset and reconnect.
83 -- This indication is auto-clearing.
84 errpar: std_logic;
85
86 -- Invalid escape sequence detected in state Run.
87 -- Triggers a reset and reconnect; auto-clearing.
88 erresc: std_logic;
89
90 -- Credit error detected. Triggers a reset and reconnect.
91 -- This indication is auto-clearing.
92 errcred: std_logic;
93
94 -- High to confirm the transmission of an N-Char.
95 -- This is a Wishbone-style handshake signal. It has a combinatorial
96 -- dependency on "txwrite".
97 txack: std_logic;
98
99 -- High for one clock cycle if a TimeCode was just received.
100 -- Verification of the TimeCode as described in 8.12.2 of ECSS-E-50
101 -- is not implemented; all received timecodes are reported.
102 tick_out: std_logic;
103
104 -- Control bits of last received TimeCode.
105 ctrl_out: std_logic_vector(1 downto 0);
106
107 -- Counter value of last received TimeCode.
108 time_out: std_logic_vector(5 downto 0);
109
110 -- High for one clock cycle if an N-Char (data byte or EOP or EEP) was
111 -- just received. The data bits must be accepted immediately from
112 -- "rxflag" and "rxdata".
113 rxchar: std_logic;
114
115 -- High if the received character is EOP or EEP, low if it is a data
116 -- byte. Valid when "rxchar" is high.
117 rxflag: std_logic;
118
119 -- Received byte, or "00000000" for EOP or "00000001" for EEP.
120 -- Valid when "rxchar" is high.
121 rxdata: std_logic_vector(7 downto 0);
122 end record;
123
124
125 -- Output signals from spwrecv to spwlink.
126 type spw_recv_out_type is record
127
128 -- High if at least one signal change was seen since enable.
129 -- Resets to low when rxen is low.
130 gotbit: std_logic;
131
132 -- High if at least one valid NULL pattern was detected since enable.
133 -- Resets to low when rxen is low.
134 gotnull: std_logic;
135
136 -- High for one clock cycle if an FCT token was just received.
137 gotfct: std_logic;
138
139 -- High for one clock cycle if a TimeCode was just received.
140 tick_out: std_logic;
141
142 -- Control bits of last received TimeCode.
143 ctrl_out: std_logic_vector(1 downto 0);
144
145 -- Counter value of last received TimeCode.
146 time_out: std_logic_vector(5 downto 0);
147
148 -- High for one clock cycle if an N-Char (data byte or EOP/EEP) was just received.
149 rxchar: std_logic;
150
151 -- High if rxchar is high and the received character is EOP or EEP.
152 -- Low if rxchar is high and the received character is a data byte.
153 rxflag: std_logic;
154
155 -- Received byte, or "00000000" for EOP or "00000001" for EEP.
156 -- Valid when "rxchar" is high.
157 rxdata: std_logic_vector(7 downto 0);
158
159 -- Disconnect detected (after a signal change was seen).
160 -- Resets to low when rxen is low or when a signal change is seen.
161 errdisc: std_logic;
162
163 -- Parity error detected (after a valid NULL pattern was seen).
164 -- Sticky; resets to low when rxen is low.
165 errpar: std_logic;
166
167 -- Escape sequence error detected (after a valid NULL pattern was seen).
168 -- Sticky; resets to low when rxen is low.
169 erresc: std_logic;
170 end record;
171
172
173 -- Input signals to spwxmit from spwlink.
174 type spw_xmit_in_type is record
175
176 -- High to enable transmitter; low to disable and reset transmitter.
177 txen: std_logic;
178
179 -- Indicates that only NULL characters may be transmitted.
180 stnull: std_logic;
181
182 -- Indicates that only NULL and/or FCT characters may be transmitted.
183 stfct: std_logic;
184
185 -- Requests transmission of an FCT character.
186 -- Keep this signal high until confirmed by "fctack".
187 fct_in: std_logic;
188
189 -- High for one clock cycle to request transmission of a TimeCode.
190 -- The request is registered inside spwxmit until it can be processed.
191 tick_in: std_logic;
192
193 -- Control bits of the TimeCode to be sent.
194 -- Must be valid while "tick_in" is high.
195 ctrl_in: std_logic_vector(1 downto 0);
196
197 -- Counter value of the TimeCode to be sent.
198 -- Must be valid while "tick_in" is high.
199 time_in: std_logic_vector(5 downto 0);
200
201 -- Request transmission of an N-Char.
202 -- Keep this signal high until confirmed by "txack".
203 txwrite: std_logic;
204
205 -- Control flag to be sent with the next N-Char.
206 -- Must be valid while "txwrite" is high.
207 txflag: std_logic;
208
209 -- Byte to send, or "00000000" for EOP or "00000001" for EEP.
210 -- Must be valid while "txwrite" is high.
211 txdata: std_logic_vector(7 downto 0);
212 end record;
213
214
215 -- Output signals from spwxmit to spwlink.
216 type spw_xmit_out_type is record
217
218 -- High to confirm transmission on an FCT character.
219 -- This is a Wishbone-style handshaking signal; it is combinatorially
220 -- dependent on "fct_in".
221 fctack: std_logic;
222
223 -- High to confirm transmission of an N-Char.
224 -- This is a Wishbone-style handshaking signal; it is combinatorially
225 -- dependent on both "fct_in" and "txwrite".
226 txack: std_logic;
227 end record;
228
229
230 -- Character-stream interface
231 component spwstream is
232 generic (
233 sysfreq: real; -- clk freq in Hz
234 txclkfreq: real := 0.0; -- txclk freq in Hz
235 rximpl: spw_implementation_type := impl_generic;
236 rxchunk: integer range 1 to 4 := 1; -- max bits per clk
237 tximpl: spw_implementation_type := impl_generic;
238 rxfifosize_bits: integer range 6 to 14 := 11; -- rx fifo size
239 txfifosize_bits: integer range 2 to 14 := 11 -- tx fifo size
240 );
241 port (
242 clk: in std_logic; -- system clock
243 rxclk: in std_logic; -- receiver sample clock
244 txclk: in std_logic; -- transmit clock
245 rst: in std_logic; -- synchronous reset
246 autostart: in std_logic; -- automatic link start
247 linkstart: in std_logic; -- forced link start
248 linkdis: in std_logic; -- stop link
249 txdivcnt: in std_logic_vector(7 downto 0); -- tx scale factor
250 tick_in: in std_logic; -- request timecode xmit
251 ctrl_in: in std_logic_vector(1 downto 0);
252 time_in: in std_logic_vector(5 downto 0);
253 txwrite: in std_logic; -- request character xmit
254 txflag: in std_logic; -- control flag of tx char
255 txdata: in std_logic_vector(7 downto 0);
256 txrdy: out std_logic; -- room in tx fifo
257 txhalff: out std_logic; -- tx fifo half full
258 tick_out: out std_logic; -- timecode received
259 ctrl_out: out std_logic_vector(1 downto 0);
260 time_out: out std_logic_vector(5 downto 0);
261 rxvalid: out std_logic; -- rx fifo not empty
262 rxhalff: out std_logic; -- rx fifo half full
263 rxflag: out std_logic; -- control flag of rx char
264 rxdata: out std_logic_vector(7 downto 0);
265 rxread: in std_logic; -- accept rx character
266 started: out std_logic; -- link in Started state
267 connecting: out std_logic; -- link in Connecting state
268 running: out std_logic; -- link in Run state
269 errdisc: out std_logic; -- disconnect error
270 errpar: out std_logic; -- parity error
271 erresc: out std_logic; -- escape error
272 errcred: out std_logic; -- credit error
273 spw_di: in std_logic;
274 spw_si: in std_logic;
275 spw_do: out std_logic;
276 spw_so: out std_logic
277 );
278 end component spwstream;
279
280
281 -- Link Level Interface
282 component spwlink is
283 generic (
284 reset_time: integer -- reset time in clocks (6.4 us)
285 );
286 port (
287 clk: in std_logic; -- system clock
288 rst: in std_logic; -- synchronous reset (active-high)
289 linki: in spw_link_in_type;
290 linko: out spw_link_out_type;
291 rxen: out std_logic;
292 recvo: in spw_recv_out_type;
293 xmiti: out spw_xmit_in_type;
294 xmito: in spw_xmit_out_type
295 );
296 end component spwlink;
297
298
299 -- Receiver
300 component spwrecv is
301 generic (
302 disconnect_time: integer range 1 to 255; -- disconnect period in system clock cycles
303 rxchunk: integer range 1 to 4 -- nr of bits per system clock
304 );
305 port (
306 clk: in std_logic; -- system clock
307 rxen: in std_logic; -- receiver enabled
308 recvo: out spw_recv_out_type;
309 inact: in std_logic;
310 inbvalid: in std_logic;
311 inbits: in std_logic_vector(rxchunk-1 downto 0)
312 );
313 end component spwrecv;
314
315
316 -- Transmitter (generic implementation)
317 component spwxmit is
318 port (
319 clk: in std_logic; -- system clock
320 rst: in std_logic; -- synchronous reset (active-high)
321 divcnt: in std_logic_vector(7 downto 0);
322 xmiti: in spw_xmit_in_type;
323 xmito: out spw_xmit_out_type;
324 spw_do: out std_logic; -- tx data to SPW bus
325 spw_so: out std_logic -- tx strobe to SPW bus
326 );
327 end component spwxmit;
328
329
330 -- Transmitter (separate tx clock domain)
331 component spwxmit_fast is
332 port (
333 clk: in std_logic; -- system clock
334 txclk: in std_logic; -- transmit clock
335 rst: in std_logic; -- synchronous reset (active-high)
336 divcnt: in std_logic_vector(7 downto 0);
337 xmiti: in spw_xmit_in_type;
338 xmito: out spw_xmit_out_type;
339 spw_do: out std_logic; -- tx data to SPW bus
340 spw_so: out std_logic -- tx strobe to SPW bus
341 );
342 end component spwxmit_fast;
343
344
345 -- Front-end for SpaceWire Receiver (generic implementation)
346 component spwrecvfront_generic is
347 port (
348 clk: in std_logic; -- system clock
349 rxen: in std_logic; -- high to enable receiver
350 inact: out std_logic; -- high if activity on input
351 inbvalid: out std_logic; -- high if inbits contains a valid received bit
352 inbits: out std_logic_vector(0 downto 0); -- received bit
353 spw_di: in std_logic; -- Data In signal from SpaceWire bus
354 spw_si: in std_logic -- Strobe In signal from SpaceWire bus
355 );
356 end component spwrecvfront_generic;
357
358
359 -- Front-end for SpaceWire Receiver (separate rx clock domain)
360 component spwrecvfront_fast is
361 generic (
362 rxchunk: integer range 1 to 4 -- max number of bits per system clock
363 );
364 port (
365 clk: in std_logic; -- system clock
366 rxclk: in std_logic; -- sample clock (DDR)
367 rxen: in std_logic; -- high to enable receiver
368 inact: out std_logic; -- high if activity on input
369 inbvalid: out std_logic; -- high if inbits contains a valid group of received bits
370 inbits: out std_logic_vector(rxchunk-1 downto 0); -- received bits
371 spw_di: in std_logic; -- Data In signal from SpaceWire bus
372 spw_si: in std_logic -- Strobe In signal from SpaceWire bus
373 );
374 end component spwrecvfront_fast;
375
376
377 -- Synchronous two-port memory.
378 component spwram is
379 generic (
380 abits: integer;
381 dbits: integer );
382 port (
383 rclk: in std_logic;
384 wclk: in std_logic;
385 ren: in std_logic;
386 raddr: in std_logic_vector(abits-1 downto 0);
387 rdata: out std_logic_vector(dbits-1 downto 0);
388 wen: in std_logic;
389 waddr: in std_logic_vector(abits-1 downto 0);
390 wdata: in std_logic_vector(dbits-1 downto 0) );
391 end component spwram;
392
393
394 -- Double flip-flop synchronizer.
395 component syncdff is
396 port (
397 clk: in std_logic; -- clock (destination domain)
398 rst: in std_logic; -- asynchronous reset, active-high
399 di: in std_logic; -- input data
400 do: out std_logic ); -- output data
401 end component syncdff;
402
403 end package;
@@ -0,0 +1,58
1 --
2 -- Synchronous two-port RAM with separate clocks for read and write ports.
3 -- The synthesizer for Xilinx Spartan-3 will infer Block RAM for this entity.
4 --
5
6 library ieee;
7 use ieee.std_logic_1164.all;
8 use ieee.numeric_std.all;
9
10 entity spwram is
11
12 generic (
13 abits: integer;
14 dbits: integer );
15
16 port (
17 rclk: in std_logic;
18 wclk: in std_logic;
19 ren: in std_logic;
20 raddr: in std_logic_vector(abits-1 downto 0);
21 rdata: out std_logic_vector(dbits-1 downto 0);
22 wen: in std_logic;
23 waddr: in std_logic_vector(abits-1 downto 0);
24 wdata: in std_logic_vector(dbits-1 downto 0) );
25
26 end entity spwram;
27
28 architecture spwram_arch of spwram is
29
30 type mem_type is array(0 to (2**abits - 1)) of
31 std_logic_vector(dbits-1 downto 0);
32
33 signal s_mem: mem_type;
34
35 begin
36
37 -- read process
38 process (rclk) is
39 begin
40 if rising_edge(rclk) then
41 if ren = '1' then
42 rdata <= s_mem(to_integer(unsigned(raddr)));
43 end if;
44 end if;
45 end process;
46
47 -- write process
48 process (wclk) is
49 begin
50 if rising_edge(wclk) then
51 if wen = '1' then
52 s_mem(to_integer(unsigned(waddr))) <= wdata;
53 end if;
54 end if;
55 end process;
56
57 end architecture;
58
@@ -0,0 +1,267
1 --
2 -- SpaceWire Receiver
3 --
4 -- This entity decodes the sequence of incoming data bits into tokens.
5 -- Data bits are passed to this entity from the Receiver Front-end
6 -- in groups of rxchunk bits at a time.
7 --
8 -- The bitrate of the incoming SpaceWire signal must be strictly less
9 -- than rxchunk times the system clock frequency.
10 --
11
12 library ieee;
13 use ieee.std_logic_1164.all, ieee.numeric_std.all;
14 use work.spwpkg.all;
15
16 entity spwrecv is
17
18 generic (
19 -- Disconnect timeout, expressed in system clock cycles.
20 -- Should be 850 ns (727 ns .. 1000 ns) according to the standard.
21 disconnect_time: integer range 1 to 255;
22
23 -- Nr of bits sampled per system clock.
24 rxchunk: integer range 1 to 4
25 );
26
27 port (
28 -- System clock.
29 clk: in std_logic;
30
31 -- High to enable receiver; low to disable and reset receiver.
32 rxen: in std_logic;
33
34 -- Output signals to spwlink.
35 recvo: out spw_recv_out_type;
36
37 -- High if there has been recent activity on the input lines.
38 inact: in std_logic;
39
40 -- High if inbits contains a valid group of received bits.
41 inbvalid: in std_logic;
42
43 -- Received bits from receiver front-end.
44 inbits: in std_logic_vector(rxchunk-1 downto 0)
45 );
46
47 end entity spwrecv;
48
49 architecture spwrecv_arch of spwrecv is
50
51 -- registers
52 type regs_type is record
53 -- receiver state
54 bit_seen: std_ulogic; -- got a bit transition
55 null_seen: std_ulogic; -- got a NULL token
56 -- input shift register
57 bitshift: std_logic_vector(8 downto 0);
58 bitcnt: std_logic_vector(9 downto 0); -- one-hot counter
59 -- parity flag
60 parity: std_ulogic;
61 -- decoding
62 control: std_ulogic; -- next code is control code
63 escaped: std_ulogic; -- last code was ESC
64 -- output registers
65 gotfct: std_ulogic;
66 tick_out: std_ulogic;
67 rxchar: std_ulogic;
68 rxflag: std_ulogic;
69 timereg: std_logic_vector(7 downto 0);
70 datareg: std_logic_vector(7 downto 0);
71 -- disconnect timer
72 disccnt: unsigned(7 downto 0);
73 -- error flags
74 errpar: std_ulogic;
75 erresc: std_ulogic;
76 end record;
77
78 -- Initial state
79 constant regs_reset: regs_type := (
80 bit_seen => '0',
81 null_seen => '0',
82 bitshift => (others => '1'),
83 bitcnt => (others => '0'),
84 parity => '0',
85 control => '0',
86 escaped => '0',
87 gotfct => '0',
88 tick_out => '0',
89 rxchar => '0',
90 rxflag => '0',
91 timereg => (others => '0'),
92 datareg => (others => '0'),
93 disccnt => "00000000",
94 errpar => '0',
95 erresc => '0' );
96
97 -- registers
98 signal r: regs_type := regs_reset;
99 signal rin: regs_type;
100
101 begin
102
103 -- combinatorial process
104 process (r, rxen, inact, inbvalid, inbits)
105 variable v: regs_type;
106 variable v_inbit: std_ulogic;
107 begin
108 v := r;
109 v_inbit := '0';
110
111 -- disconnect timer
112 if inact = '1' then
113 -- activity on input; reset timer
114 v.disccnt := to_unsigned(disconnect_time, v.disccnt'length);
115 elsif r.disccnt /= 0 then
116 -- count down
117 v.disccnt := r.disccnt - 1;
118 end if;
119
120 -- assume no new token
121 v.gotfct := '0';
122 v.tick_out := '0';
123 v.rxchar := '0';
124
125 if inbvalid = '1' then
126
127 -- process incoming bits
128 for i in 0 to rxchunk-1 loop
129 v_inbit := inbits(i);
130
131 -- got a bit transition
132 v.bit_seen := '1';
133
134 if v.bitcnt(0) = '1' then
135 -- received new token
136 -- note that this will not happen before null_seen='1'
137 if (v.parity xor v_inbit) = '0' then
138 -- Parity check failed.
139 v.errpar := '1';
140 else
141 if v.control = '1' then
142 -- received control code
143 case v.bitshift(7 downto 6) is
144 when "00" => -- FCT or NULL
145 v.gotfct := not r.escaped;
146 v.escaped := '0';
147 when "10" => -- EOP
148 if r.escaped = '1' then
149 v.erresc := '1';
150 end if;
151 v.escaped := '0';
152 v.rxchar := not r.escaped;
153 v.rxflag := '1';
154 v.datareg := "00000000";
155 when "01" => -- EEP
156 if r.escaped = '1' then
157 v.erresc := '1';
158 end if;
159 v.escaped := '0';
160 v.rxchar := not r.escaped;
161 v.rxflag := '1';
162 v.datareg := "00000001";
163 when others => -- ESC
164 if r.escaped = '1' then
165 v.erresc := '1';
166 end if;
167 v.escaped := '1';
168 end case;
169 else
170 -- received 8-bit character
171 if r.escaped = '1' then
172 -- received Time-Code
173 v.tick_out := '1';
174 v.timereg := v.bitshift(7 downto 0);
175 else
176 -- received data character
177 v.rxflag := '0';
178 v.rxchar := '1';
179 v.datareg := v.bitshift(7 downto 0);
180 end if;
181 v.escaped := '0';
182 end if;
183 end if;
184 -- prepare for next code
185 v.parity := '0';
186 v.control := v_inbit;
187 if v_inbit = '1' then
188 -- next word will be control code.
189 v.bitcnt := (3 => '1', others => '0');
190 else
191 -- next word will be a data byte.
192 v.bitcnt := (9 => '1', others => '0');
193 end if;
194 else
195 -- wait until next code is completely received;
196 -- accumulate parity
197 v.bitcnt := '0' & v.bitcnt(9 downto 1);
198 v.parity := v.parity xor v_inbit;
199 end if;
200
201 -- detect first NULL
202 if v.null_seen = '0' then
203 if v.bitshift = "000101110" then
204 -- got first NULL pattern
205 v.null_seen := '1';
206 v.control := v_inbit; -- should always be '1'
207 v.parity := '0';
208 v.bitcnt := (3 => '1', others => '0');
209 end if;
210 end if;
211
212 -- shift new bit into register.
213 v.bitshift := v_inbit & v.bitshift(v.bitshift'high downto 1);
214
215 end loop;
216 end if;
217
218 -- synchronous reset
219 if rxen = '0' then
220 v.bit_seen := '0';
221 v.null_seen := '0';
222 v.bitshift := "111111111";
223 v.bitcnt := (others => '0');
224 v.gotfct := '0';
225 v.tick_out := '0';
226 v.rxchar := '0';
227 v.rxflag := '0';
228 v.escaped := '0';
229 v.timereg := "00000000";
230 v.datareg := "00000000";
231 v.disccnt := to_unsigned(0, v.disccnt'length);
232 v.errpar := '0';
233 v.erresc := '0';
234 end if;
235
236 -- drive outputs
237 recvo.gotbit <= r.bit_seen;
238 recvo.gotnull <= r.null_seen;
239 recvo.gotfct <= r.gotfct;
240 recvo.tick_out <= r.tick_out;
241 recvo.ctrl_out <= r.timereg(7 downto 6);
242 recvo.time_out <= r.timereg(5 downto 0);
243 recvo.rxchar <= r.rxchar;
244 recvo.rxflag <= r.rxflag;
245 recvo.rxdata <= r.datareg;
246 if r.bit_seen = '1' and r.disccnt = 0 then
247 recvo.errdisc <= '1';
248 else
249 recvo.errdisc <= '0';
250 end if;
251 recvo.errpar <= r.errpar;
252 recvo.erresc <= r.erresc;
253
254 -- update registers
255 rin <= v;
256
257 end process;
258
259 -- update registers on rising edge of system clock
260 process (clk) is
261 begin
262 if rising_edge(clk) then
263 r <= rin;
264 end if;
265 end process;
266
267 end architecture spwrecv_arch;
@@ -0,0 +1,424
1 --
2 -- Front-end for SpaceWire Receiver
3 --
4 -- This entity samples the input signals DataIn and StrobeIn to detect
5 -- valid bit transitions. Received bits are handed to the application
6 -- in groups of "rxchunk" bits at a time, synchronous to the system clock.
7 --
8 -- This receiver is based on synchronous oversampling of the input signals.
9 -- Inputs are sampled on the rising and falling edges of an externally
10 -- supplied sample clock "rxclk". Therefore the maximum bitrate of the
11 -- incoming signal must be significantly lower than two times the "rxclk"
12 -- clock frequency. The maximum incoming bitrate must also be strictly
13 -- lower than rxchunk times the system clock frequency.
14 --
15 -- This code is tuned for implementation on Xilinx Spartan-3.
16 --
17 -- Details
18 -- -------
19 --
20 -- Stage A: The inputs "spw_di" and "spw_si" are handled as DDR signals,
21 -- synchronously sampled on both edges of "rxclk".
22 --
23 -- Stage B: The input signals are re-registered on the rising edge of "rxclk"
24 -- for further processing. This implies that every rising edge of "rxclk"
25 -- produces two new samples of "spw_di" and two new samples of "spw_si".
26 --
27 -- Stage C: Transitions in input signals are detected by comparing the XOR
28 -- of data and strobe to the XOR of the previous data and strobe samples.
29 -- If there is a difference, we know that either data or strobe has changed
30 -- and the new value of data is a valid new bit. Every rising edge of "rxclk"
31 -- thus produces either zero, or one or two new data bits.
32 --
33 -- Stage D: Received bits are collected in groups of "rxchunk" bits
34 -- (unless rxchunk=1, in which case groups of 2 bits are used). Complete
35 -- groups are pushed into an 8-deep cyclic buffer. A 3-bit counter "headptr"
36 -- indicates the current position in the cyclic buffer.
37 --
38 -- The system clock domain reads bit groups from the cyclic buffer. A tail
39 -- pointer indicates the next location to read from the buffer. A comparison
40 -- between the "tailptr" and a re-synchronized copy of the "headptr" determines
41 -- whether valid bits are available in the buffer.
42 --
43 -- Activity detection is based on a 3-bit counter "bitcnt". This counter is
44 -- incremented whenever the rxclk domain receives 1 or 2 new bits. The system
45 -- clock domain monitors a re-synchronized copy of the activity counter to
46 -- determine whether it has been updated since the previous system clock cycle.
47 --
48 -- Implementation guidelines
49 -- -------------------------
50 --
51 -- IOB flip-flops must be used to sample spw_di and spw_si.
52 -- Clock skew between the IOBs for spw_di and spw_si must be minimized.
53 --
54 -- "rxclk" must be at least as fast as the system clock;
55 -- "rxclk" does not need to be phase-related to the system clock;
56 -- it is allowed for "rxclk" to be equal to the system clock.
57 --
58 -- The following timing constraints are needed:
59 -- * PERIOD constraint on the system clock;
60 -- * PERIOD constraint on "rxclk";
61 -- * FROM-TO constraint from "rxclk" to system clock, equal to one "rxclk" period;
62 -- * FROM-TO constraint from system clock to "rxclk", equal to one "rxclk" period.
63 --
64
65 library ieee;
66 use ieee.std_logic_1164.all;
67 use ieee.numeric_std.all;
68 use work.spwpkg.all;
69
70 entity spwrecvfront_fast is
71
72 generic (
73 -- Number of bits to pass to the application per system clock.
74 rxchunk: integer range 1 to 4 );
75
76 port (
77 -- System clock.
78 clk: in std_logic;
79
80 -- Sample clock.
81 rxclk: in std_logic;
82
83 -- High to enable receiver; low to disable and reset receiver.
84 rxen: in std_logic;
85
86 -- High if there has been recent activity on the input lines.
87 inact: out std_logic;
88
89 -- High if inbits contains a valid group of received bits.
90 -- If inbvalid='1', the application must sample inbits on
91 -- the rising edge of clk.
92 inbvalid: out std_logic;
93
94 -- Received bits (bit 0 is the earliest received bit).
95 inbits: out std_logic_vector(rxchunk-1 downto 0);
96
97 -- Data In signal from SpaceWire bus.
98 spw_di: in std_logic;
99
100 -- Strobe In signal from SpaceWire bus.
101 spw_si: in std_logic );
102
103 -- Turn off FSM extraction.
104 -- Without this, XST will happily apply one-hot encoding to rrx.headptr.
105 attribute FSM_EXTRACT: string;
106 attribute FSM_EXTRACT of spwrecvfront_fast: entity is "NO";
107
108 end entity spwrecvfront_fast;
109
110 architecture spwrecvfront_arch of spwrecvfront_fast is
111
112 -- width of bit groups in cyclic buffer;
113 -- typically equal to rxchunk, except when rxchunk = 1
114 type memwidth_array_type is array(1 to 4) of integer;
115 constant chunk_to_memwidth: memwidth_array_type := ( 2, 2, 3, 4 );
116 constant memwidth: integer := chunk_to_memwidth(rxchunk);
117
118 -- registers in rxclk domain
119 type rxregs_type is record
120 -- stage B: re-register input samples
121 b_di0: std_ulogic;
122 b_si0: std_ulogic;
123 b_di1: std_ulogic;
124 b_si1: std_ulogic;
125 -- stage C: data/strobe decoding
126 c_bit: std_logic_vector(1 downto 0);
127 c_val: std_logic_vector(1 downto 0);
128 c_xor1: std_ulogic;
129 -- stage D: collect groups of memwidth bits
130 d_shift: std_logic_vector(memwidth-1 downto 0);
131 d_count: std_logic_vector(memwidth-1 downto 0);
132 -- cyclic buffer access
133 bufdata: std_logic_vector(memwidth-1 downto 0);
134 bufwrite: std_ulogic;
135 headptr: std_logic_vector(2 downto 0);
136 -- activity detection
137 bitcnt: std_logic_vector(2 downto 0);
138 end record;
139
140 -- registers in system clock domain
141 type regs_type is record
142 -- data path from buffer to output
143 tailptr: std_logic_vector(2 downto 0);
144 inbvalid: std_ulogic;
145 -- split 2-bit groups if rxchunk=1
146 splitbit: std_ulogic;
147 splitinx: std_ulogic;
148 splitvalid: std_ulogic;
149 -- activity detection
150 bitcntp: std_logic_vector(2 downto 0);
151 inact: std_ulogic;
152 -- reset signal towards rxclk domain
153 rxdis: std_ulogic;
154 end record;
155
156 constant regs_reset: regs_type := (
157 tailptr => "000",
158 inbvalid => '0',
159 splitbit => '0',
160 splitinx => '0',
161 splitvalid => '0',
162 bitcntp => "000",
163 inact => '0',
164 rxdis => '1' );
165
166 -- Signals that are re-synchronized from rxclk to system clock domain.
167 type syncsys_type is record
168 headptr: std_logic_vector(2 downto 0); -- pointer in cyclic buffer
169 bitcnt: std_logic_vector(2 downto 0); -- activity detection
170 end record;
171
172 -- Registers.
173 signal r: regs_type := regs_reset;
174 signal rin: regs_type;
175 signal rrx, rrxin: rxregs_type;
176
177 -- Synchronized signals after crossing clock domains.
178 signal syncrx_rstn: std_logic;
179 signal syncsys: syncsys_type;
180
181 -- Output data from cyclic buffer.
182 signal s_bufdout: std_logic_vector(memwidth-1 downto 0);
183
184 -- stage A: input flip-flops for rising/falling rxclk
185 signal s_a_di0: std_logic;
186 signal s_a_si0: std_logic;
187 signal s_a_di1: std_logic;
188 signal s_a_si1: std_logic;
189 signal s_a_di2: std_logic;
190 signal s_a_si2: std_logic;
191
192 -- force use of IOB flip-flops
193 attribute IOB: string;
194 attribute IOB of s_a_di1: signal is "TRUE";
195 attribute IOB of s_a_si1: signal is "TRUE";
196 attribute IOB of s_a_di2: signal is "TRUE";
197 attribute IOB of s_a_si2: signal is "TRUE";
198
199 begin
200
201 -- Cyclic data buffer.
202 bufmem: spwram
203 generic map (
204 abits => 3,
205 dbits => memwidth )
206 port map (
207 rclk => clk,
208 wclk => rxclk,
209 ren => '1',
210 raddr => r.tailptr,
211 rdata => s_bufdout,
212 wen => rrx.bufwrite,
213 waddr => rrx.headptr,
214 wdata => rrx.bufdata );
215
216 -- Synchronize reset signal for rxclk domain.
217 syncrx_reset: syncdff
218 port map ( clk => rxclk, rst => r.rxdis, di => '1', do => syncrx_rstn );
219
220 -- Synchronize signals from rxclk domain to system clock domain.
221 syncsys_headptr0: syncdff
222 port map ( clk => clk, rst => r.rxdis, di => rrx.headptr(0), do => syncsys.headptr(0) );
223 syncsys_headptr1: syncdff
224 port map ( clk => clk, rst => r.rxdis, di => rrx.headptr(1), do => syncsys.headptr(1) );
225 syncsys_headptr2: syncdff
226 port map ( clk => clk, rst => r.rxdis, di => rrx.headptr(2), do => syncsys.headptr(2) );
227 syncsys_bitcnt0: syncdff
228 port map ( clk => clk, rst => r.rxdis, di => rrx.bitcnt(0), do => syncsys.bitcnt(0) );
229 syncsys_bitcnt1: syncdff
230 port map ( clk => clk, rst => r.rxdis, di => rrx.bitcnt(1), do => syncsys.bitcnt(1) );
231 syncsys_bitcnt2: syncdff
232 port map ( clk => clk, rst => r.rxdis, di => rrx.bitcnt(2), do => syncsys.bitcnt(2) );
233
234 -- sample inputs on rising edge of rxclk
235 process (rxclk) is
236 begin
237 if rising_edge(rxclk) then
238 s_a_di1 <= spw_di;
239 s_a_si1 <= spw_si;
240 end if;
241 end process;
242
243 -- sample inputs on falling edge of rxclk
244 process (rxclk) is
245 begin
246 if falling_edge(rxclk) then
247 s_a_di2 <= spw_di;
248 s_a_si2 <= spw_si;
249 -- reregister inputs in fabric flip-flops
250 s_a_di0 <= s_a_di2;
251 s_a_si0 <= s_a_si2;
252 end if;
253 end process;
254
255 -- combinatorial process
256 process (r, rrx, rxen, syncrx_rstn, syncsys, s_bufdout, s_a_di0, s_a_si0, s_a_di1, s_a_si1)
257 variable v: regs_type;
258 variable vrx: rxregs_type;
259 begin
260 v := r;
261 vrx := rrx;
262
263 -- ---- SAMPLE CLOCK DOMAIN ----
264
265 -- stage B: re-register input samples
266 vrx.b_di0 := s_a_di0;
267 vrx.b_si0 := s_a_si0;
268 vrx.b_di1 := s_a_di1;
269 vrx.b_si1 := s_a_si1;
270
271 -- stage C: decode data/strobe and detect valid bits
272 if (rrx.b_di0 xor rrx.b_si0 xor rrx.c_xor1) = '1' then
273 vrx.c_bit(0) := rrx.b_di0;
274 else
275 vrx.c_bit(0) := rrx.b_di1;
276 end if;
277 vrx.c_bit(1) := rrx.b_di1;
278 vrx.c_val(0) := (rrx.b_di0 xor rrx.b_si0 xor rrx.c_xor1) or
279 (rrx.b_di0 xor rrx.b_si0 xor rrx.b_di1 xor rrx.b_si1);
280 vrx.c_val(1) := (rrx.b_di0 xor rrx.b_si0 xor rrx.c_xor1) and
281 (rrx.b_di0 xor rrx.b_si0 xor rrx.b_di1 xor rrx.b_si1);
282 vrx.c_xor1 := rrx.b_di1 xor rrx.b_si1;
283
284 -- Note:
285 -- c_val = "00" if no new bits are received
286 -- c_val = "01" if one new bit is received; the new bit is in c_bit(0)
287 -- c_val = "11" if two new bits are received
288
289 -- stage D: collect groups of memwidth bits
290 if rrx.c_val(0) = '1' then
291
292 -- shift incoming bits into register
293 if rrx.c_val(1) = '1' then
294 vrx.d_shift := rrx.c_bit & rrx.d_shift(memwidth-1 downto 2);
295 else
296 vrx.d_shift := rrx.c_bit(0) & rrx.d_shift(memwidth-1 downto 1);
297 end if;
298
299 -- prepare to store a group of memwidth bits
300 if rrx.d_count(0) = '1' then
301 -- only one more bit needed
302 vrx.bufdata := rrx.c_bit(0) & rrx.d_shift(memwidth-1 downto 1);
303 else
304 vrx.bufdata := rrx.c_bit & rrx.d_shift(memwidth-1 downto 2);
305 end if;
306
307 -- countdown nr of needed bits (one-hot counter)
308 if rrx.c_val(1) = '1' then
309 vrx.d_count := rrx.d_count(1 downto 0) & rrx.d_count(memwidth-1 downto 2);
310 else
311 vrx.d_count := rrx.d_count(0 downto 0) & rrx.d_count(memwidth-1 downto 1);
312 end if;
313
314 end if;
315
316 -- stage D: store groups of memwidth bits
317 vrx.bufwrite := rrx.c_val(0) and (rrx.d_count(0) or (rrx.c_val(1) and rrx.d_count(1)));
318
319 -- Increment head pointer.
320 if rrx.bufwrite = '1' then
321 vrx.headptr := std_logic_vector(unsigned(rrx.headptr) + 1);
322 end if;
323
324 -- Activity detection.
325 if rrx.c_val(0) = '1' then
326 vrx.bitcnt := std_logic_vector(unsigned(rrx.bitcnt) + 1);
327 end if;
328
329 -- Synchronous reset of rxclk domain.
330 if syncrx_rstn = '0' then
331 vrx.c_val := "00";
332 vrx.c_xor1 := '0';
333 vrx.d_count := (others => '0');
334 vrx.d_count(memwidth-1) := '1';
335 vrx.bufwrite := '0';
336 vrx.headptr := "000";
337 vrx.bitcnt := "000";
338 end if;
339
340 -- ---- SYSTEM CLOCK DOMAIN ----
341
342 -- Compare tailptr to headptr to decide whether there is new data.
343 -- If the values are equal, we are about to read a location which has
344 -- not yet been written by the rxclk domain.
345 if r.tailptr = syncsys.headptr then
346 -- No more data in cyclic buffer.
347 v.inbvalid := '0';
348 else
349 -- Reading valid data from cyclic buffer.
350 v.inbvalid := '1';
351 -- Increment tail pointer.
352 if rxchunk /= 1 then
353 v.tailptr := std_logic_vector(unsigned(r.tailptr) + 1);
354 end if;
355 end if;
356
357 -- If rxchunk=1, split 2-bit groups into separate bits.
358 if rxchunk = 1 then
359 -- Select one of the two bits.
360 if r.splitinx = '0' then
361 v.splitbit := s_bufdout(0);
362 else
363 v.splitbit := s_bufdout(1);
364 end if;
365 -- Indicate valid bit.
366 v.splitvalid := r.inbvalid;
367 -- Increment tail pointer.
368 if r.inbvalid = '1' then
369 v.splitinx := not r.splitinx;
370 if r.splitinx = '0' then
371 v.tailptr := std_logic_vector(unsigned(r.tailptr) + 1);
372 end if;
373 end if;
374 end if;
375
376 -- Activity detection.
377 v.bitcntp := syncsys.bitcnt;
378 if r.bitcntp = syncsys.bitcnt then
379 v.inact := '0';
380 else
381 v.inact := '1';
382 end if;
383
384 -- Synchronous reset of system clock domain.
385 if rxen = '0' then
386 v := regs_reset;
387 end if;
388
389 -- Register rxen to ensure glitch-free signal to rxclk domain
390 v.rxdis := not rxen;
391
392 -- drive outputs
393 inact <= r.inact;
394 if rxchunk = 1 then
395 inbvalid <= r.splitvalid;
396 inbits(0) <= r.splitbit;
397 else
398 inbvalid <= r.inbvalid;
399 inbits <= s_bufdout;
400 end if;
401
402 -- update registers
403 rrxin <= vrx;
404 rin <= v;
405
406 end process;
407
408 -- update registers on rising edge of rxclk
409 process (rxclk) is
410 begin
411 if rising_edge(rxclk) then
412 rrx <= rrxin;
413 end if;
414 end process;
415
416 -- update registers on rising edge of system clock
417 process (clk) is
418 begin
419 if rising_edge(clk) then
420 r <= rin;
421 end if;
422 end process;
423
424 end architecture spwrecvfront_arch;
@@ -0,0 +1,96
1 --
2 -- Front-end for SpaceWire Receiver
3 --
4 -- This entity samples the input signals DataIn and StrobeIn to detect
5 -- valid bit transitions. Received bits are handed to the application.
6 --
7 -- Inputs are sampled on the rising edge of the system clock, therefore
8 -- the maximum bitrate of the incoming signal must be significantly lower
9 -- than system clock frequency.
10 --
11
12 library ieee;
13 use ieee.std_logic_1164.all;
14 use ieee.numeric_std.all;
15
16 entity spwrecvfront_generic is
17
18 port (
19 -- System clock.
20 clk: in std_logic;
21
22 -- High to enable receiver; low to disable and reset receiver.
23 rxen: in std_logic;
24
25 -- High if there has been recent activity on the input lines.
26 inact: out std_logic;
27
28 -- High if inbits contains a valid received bit.
29 -- If inbvalid='1', the application must sample inbits on
30 -- the rising edge of clk.
31 inbvalid: out std_logic;
32
33 -- Received bit
34 inbits: out std_logic_vector(0 downto 0);
35
36 -- Data In signal from SpaceWire bus.
37 spw_di: in std_logic;
38
39 -- Strobe In signal from SpaceWire bus.
40 spw_si: in std_logic );
41
42 end entity spwrecvfront_generic;
43
44 architecture spwrecvfront_arch of spwrecvfront_generic is
45
46 -- input flip-flops
47 signal s_spwdi1: std_ulogic;
48 signal s_spwsi1: std_ulogic;
49 signal s_spwdi2: std_ulogic;
50 signal s_spwsi2: std_ulogic;
51
52 -- data/strobe decoding
53 signal s_spwsi3: std_ulogic;
54
55 -- output registers
56 signal s_inbvalid: std_ulogic;
57 signal s_inbit: std_ulogic;
58
59 begin
60
61 -- drive outputs
62 inact <= s_inbvalid;
63 inbvalid <= s_inbvalid;
64 inbits(0) <= s_inbit;
65
66 -- synchronous process
67 process (clk) is
68 begin
69 if rising_edge(clk) then
70
71 -- sample input signal
72 s_spwdi1 <= spw_di;
73 s_spwsi1 <= spw_si;
74
75 -- more flip-flops for safe synchronization
76 s_spwdi2 <= s_spwdi1;
77 s_spwsi2 <= s_spwsi1;
78
79 -- keep strobe signal for data/strobe decoding
80 s_spwsi3 <= s_spwsi2;
81
82 -- keep data bit for data/strobe decoding
83 s_inbit <= s_spwdi2;
84
85 if rxen = '1' then
86 -- data/strobe decoding
87 s_inbvalid <= s_spwdi2 xor s_spwsi2 xor s_inbit xor s_spwsi3;
88 else
89 -- reset receiver
90 s_inbvalid <= '0';
91 end if;
92
93 end if;
94 end process;
95
96 end architecture spwrecvfront_arch;
This diff has been collapsed as it changes many lines, (547 lines changed) Show them Hide them
@@ -0,0 +1,547
1 --
2 -- SpaceWire core with character-stream interface.
3 --
4 -- This entity provides a SpaceWire core with a character-stream interface.
5 -- The interface provides means for connection initiation, sending and
6 -- receiving of N-Chars and TimeCodes, and error reporting.
7 --
8 -- This entity instantiates spwlink, spwrecv, spwxmit and one of the
9 -- spwrecvfront implementations. It also implements a receive FIFO and
10 -- a transmit FIFO.
11 --
12 -- The SpaceWire standard requires that each transceiver use an initial
13 -- signalling rate of 10 Mbit/s. This implies that the system clock frequency
14 -- must be a multiple of 10 MHz. See the manual for further details on
15 -- bitrates and clocking.
16 --
17
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.numeric_std.all;
21 use work.spwpkg.all;
22
23 entity spwstream is
24
25 generic (
26 -- System clock frequency in Hz.
27 -- This must be set to the frequency of "clk". It is used to setup
28 -- counters for reset timing, disconnect timeout and to transmit
29 -- at 10 Mbit/s during the link handshake.
30 sysfreq: real;
31
32 -- Transmit clock frequency in Hz (only if tximpl = impl_fast).
33 -- This must be set to the frequency of "txclk". It is used to
34 -- transmit at 10 Mbit/s during the link handshake.
35 txclkfreq: real := 0.0;
36
37 -- Selection of a receiver front-end implementation.
38 rximpl: spw_implementation_type := impl_generic;
39
40 -- Maximum number of bits received per system clock
41 -- (must be 1 in case of impl_generic).
42 rxchunk: integer range 1 to 4 := 1;
43
44 -- Selection of a transmitter implementation.
45 tximpl: spw_implementation_type := impl_generic;
46
47 -- Size of the receive FIFO as the 2-logarithm of the number of bytes.
48 -- Must be at least 6 (64 bytes).
49 rxfifosize_bits: integer range 6 to 14 := 11;
50
51 -- Size of the transmit FIFO as the 2-logarithm of the number of bytes.
52 txfifosize_bits: integer range 2 to 14 := 11
53 );
54
55 port (
56 -- System clock.
57 clk: in std_logic;
58
59 -- Receiver sample clock (only for impl_fast)
60 rxclk: in std_logic;
61
62 -- Transmit clock (only for impl_fast)
63 txclk: in std_logic;
64
65 -- Synchronous reset (active-high).
66 rst: in std_logic;
67
68 -- Enables automatic link start on receipt of a NULL character.
69 autostart: in std_logic;
70
71 -- Enables link start once the Ready state is reached.
72 -- Without autostart or linkstart, the link remains in state Ready.
73 linkstart: in std_logic;
74
75 -- Do not start link (overrides linkstart and autostart) and/or
76 -- disconnect a running link.
77 linkdis: in std_logic;
78
79 -- Scaling factor minus 1, used to scale the transmit base clock into
80 -- the transmission bit rate. The system clock (for impl_generic) or
81 -- the txclk (for impl_fast) is divided by (unsigned(txdivcnt) + 1).
82 -- Changing this signal will immediately change the transmission rate.
83 -- During link setup, the transmission rate is always 10 Mbit/s.
84 txdivcnt: in std_logic_vector(7 downto 0);
85
86 -- High for one clock cycle to request transmission of a TimeCode.
87 -- The request is registered inside the entity until it can be processed.
88 tick_in: in std_logic;
89
90 -- Control bits of the TimeCode to be sent. Must be valid while tick_in is high.
91 ctrl_in: in std_logic_vector(1 downto 0);
92
93 -- Counter value of the TimeCode to be sent. Must be valid while tick_in is high.
94 time_in: in std_logic_vector(5 downto 0);
95
96 -- Pulled high by the application to write an N-Char to the transmit
97 -- queue. If "txwrite" and "txrdy" are both high on the rising edge
98 -- of "clk", a character is added to the transmit queue.
99 -- This signal has no effect if "txrdy" is low.
100 txwrite: in std_logic;
101
102 -- Control flag to be sent with the next N_Char.
103 -- Must be valid while txwrite is high.
104 txflag: in std_logic;
105
106 -- Byte to be sent, or "00000000" for EOP or "00000001" for EEP.
107 -- Must be valid while txwrite is high.
108 txdata: in std_logic_vector(7 downto 0);
109
110 -- High if the entity is ready to accept an N-Char for transmission.
111 txrdy: out std_logic;
112
113 -- High if the transmission queue is at least half full.
114 txhalff: out std_logic;
115
116 -- High for one clock cycle if a TimeCode was just received.
117 tick_out: out std_logic;
118
119 -- Control bits of the last received TimeCode.
120 ctrl_out: out std_logic_vector(1 downto 0);
121
122 -- Counter value of the last received TimeCode.
123 time_out: out std_logic_vector(5 downto 0);
124
125 -- High if "rxflag" and "rxdata" contain valid data.
126 -- This signal is high unless the receive FIFO is empty.
127 rxvalid: out std_logic;
128
129 -- High if the receive FIFO is at least half full.
130 rxhalff: out std_logic;
131
132 -- High if the received character is EOP or EEP; low if the received
133 -- character is a data byte. Valid if "rxvalid" is high.
134 rxflag: out std_logic;
135
136 -- Received byte, or "00000000" for EOP or "00000001" for EEP.
137 -- Valid if "rxvalid" is high.
138 rxdata: out std_logic_vector(7 downto 0);
139
140 -- Pulled high by the application to accept a received character.
141 -- If "rxvalid" and "rxread" are both high on the rising edge of "clk",
142 -- a character is removed from the receive FIFO and "rxvalid", "rxflag"
143 -- and "rxdata" are updated.
144 -- This signal has no effect if "rxvalid" is low.
145 rxread: in std_logic;
146
147 -- High if the link state machine is currently in the Started state.
148 started: out std_logic;
149
150 -- High if the link state machine is currently in the Connecting state.
151 connecting: out std_logic;
152
153 -- High if the link state machine is currently in the Run state, indicating
154 -- that the link is fully operational. If none of started, connecting or running
155 -- is high, the link is in an initial state and the transmitter is not yet enabled.
156 running: out std_logic;
157
158 -- Disconnect detected in state Run. Triggers a reset and reconnect of the link.
159 -- This indication is auto-clearing.
160 errdisc: out std_logic;
161
162 -- Parity error detected in state Run. Triggers a reset and reconnect of the link.
163 -- This indication is auto-clearing.
164 errpar: out std_logic;
165
166 -- Invalid escape sequence detected in state Run. Triggers a reset and reconnect of
167 -- the link. This indication is auto-clearing.
168 erresc: out std_logic;
169
170 -- Credit error detected. Triggers a reset and reconnect of the link.
171 -- This indication is auto-clearing.
172 errcred: out std_logic;
173
174 -- Data In signal from SpaceWire bus.
175 spw_di: in std_logic;
176
177 -- Strobe In signal from SpaceWire bus.
178 spw_si: in std_logic;
179
180 -- Data Out signal to SpaceWire bus.
181 spw_do: out std_logic;
182
183 -- Strobe Out signal to SpaceWire bus.
184 spw_so: out std_logic
185 );
186
187 end entity spwstream;
188
189 architecture spwstream_arch of spwstream is
190
191 -- Convert boolean to std_logic.
192 type bool_to_logic_type is array(boolean) of std_ulogic;
193 constant bool_to_logic: bool_to_logic_type := (false => '0', true => '1');
194
195 -- Reset time (6.4 us) in system clocks
196 constant reset_time: integer := integer(sysfreq * 6.4e-6);
197
198 -- Disconnect time (850 ns) in system clocks
199 constant disconnect_time: integer := integer(sysfreq * 850.0e-9);
200
201 -- Initial tx clock scaler (10 Mbit).
202 type impl_to_real_type is array(spw_implementation_type) of real;
203 constant tximpl_to_txclk_freq: impl_to_real_type :=
204 (impl_generic => sysfreq, impl_fast => txclkfreq);
205 constant effective_txclk_freq: real := tximpl_to_txclk_freq(tximpl);
206 constant default_divcnt: std_logic_vector(7 downto 0) :=
207 std_logic_vector(to_unsigned(integer(effective_txclk_freq / 10.0e6 - 1.0), 8));
208
209 -- Registers.
210 type regs_type is record
211 -- packet state
212 rxpacket: std_logic; -- '1' when receiving a packet
213 rxeep: std_logic; -- '1' when rx EEP character pending
214 txpacket: std_logic; -- '1' when transmitting a packet
215 txdiscard: std_logic; -- '1' when discarding a tx packet
216 -- FIFO pointers
217 rxfifo_raddr: std_logic_vector(rxfifosize_bits-1 downto 0);
218 rxfifo_waddr: std_logic_vector(rxfifosize_bits-1 downto 0);
219 txfifo_raddr: std_logic_vector(txfifosize_bits-1 downto 0);
220 txfifo_waddr: std_logic_vector(txfifosize_bits-1 downto 0);
221 -- FIFO state
222 rxfifo_rvalid: std_logic; -- '1' if s_rxfifo_rdata is valid
223 txfifo_rvalid: std_logic; -- '1' if s_txfifo_rdata is valid
224 rxfull: std_logic; -- '1' if RX fifo is full
225 rxhalff: std_logic; -- '1' if RX fifo is at least half full
226 txfull: std_logic; -- '1' if TX fifo is full
227 txhalff: std_logic; -- '1' if TX fifo is at least half full
228 rxroom: std_logic_vector(5 downto 0);
229 end record;
230
231 constant regs_reset: regs_type := (
232 rxpacket => '0',
233 rxeep => '0',
234 txpacket => '0',
235 txdiscard => '0',
236 rxfifo_raddr => (others => '0'),
237 rxfifo_waddr => (others => '0'),
238 txfifo_raddr => (others => '0'),
239 txfifo_waddr => (others => '0'),
240 rxfifo_rvalid => '0',
241 txfifo_rvalid => '0',
242 rxfull => '0',
243 rxhalff => '0',
244 txfull => '0',
245 txhalff => '0',
246 rxroom => (others => '0') );
247
248 signal r: regs_type := regs_reset;
249 signal rin: regs_type;
250
251 -- Interface signals to components.
252 signal recv_rxen: std_logic;
253 signal recvo: spw_recv_out_type;
254 signal recv_inact: std_logic;
255 signal recv_inbvalid: std_logic;
256 signal recv_inbits: std_logic_vector(rxchunk-1 downto 0);
257 signal xmiti: spw_xmit_in_type;
258 signal xmito: spw_xmit_out_type;
259 signal xmit_divcnt: std_logic_vector(7 downto 0);
260 signal linki: spw_link_in_type;
261 signal linko: spw_link_out_type;
262
263 -- Memory interface signals.
264 signal s_rxfifo_raddr: std_logic_vector(rxfifosize_bits-1 downto 0);
265 signal s_rxfifo_rdata: std_logic_vector(8 downto 0);
266 signal s_rxfifo_wen: std_logic;
267 signal s_rxfifo_waddr: std_logic_vector(rxfifosize_bits-1 downto 0);
268 signal s_rxfifo_wdata: std_logic_vector(8 downto 0);
269 signal s_txfifo_raddr: std_logic_vector(txfifosize_bits-1 downto 0);
270 signal s_txfifo_rdata: std_logic_vector(8 downto 0);
271 signal s_txfifo_wen: std_logic;
272 signal s_txfifo_waddr: std_logic_vector(txfifosize_bits-1 downto 0);
273 signal s_txfifo_wdata: std_logic_vector(8 downto 0);
274
275 begin
276
277 -- Instantiate link controller.
278 link_inst: spwlink
279 generic map (
280 reset_time => reset_time )
281 port map (
282 clk => clk,
283 rst => rst,
284 linki => linki,
285 linko => linko,
286 rxen => recv_rxen,
287 recvo => recvo,
288 xmiti => xmiti,
289 xmito => xmito );
290
291 -- Instantiate receiver.
292 recv_inst: spwrecv
293 generic map(
294 disconnect_time => disconnect_time,
295 rxchunk => rxchunk )
296 port map (
297 clk => clk,
298 rxen => recv_rxen,
299 recvo => recvo,
300 inact => recv_inact,
301 inbvalid => recv_inbvalid,
302 inbits => recv_inbits );
303
304 -- Instantiate transmitter.
305 xmit_sel0: if tximpl = impl_generic generate
306 xmit_inst: spwxmit
307 port map (
308 clk => clk,
309 rst => rst,
310 divcnt => xmit_divcnt,
311 xmiti => xmiti,
312 xmito => xmito,
313 spw_do => spw_do,
314 spw_so => spw_so );
315 end generate;
316 xmit_sel1: if tximpl = impl_fast generate
317 xmit_fast_inst: spwxmit_fast
318 port map (
319 clk => clk,
320 txclk => txclk,
321 rst => rst,
322 divcnt => xmit_divcnt,
323 xmiti => xmiti,
324 xmito => xmito,
325 spw_do => spw_do,
326 spw_so => spw_so );
327 end generate;
328
329 -- Instantiate receiver front-end.
330 recvfront_sel0: if rximpl = impl_generic generate
331 recvfront_generic_inst: spwrecvfront_generic
332 port map (
333 clk => clk,
334 rxen => recv_rxen,
335 inact => recv_inact,
336 inbvalid => recv_inbvalid,
337 inbits => recv_inbits,
338 spw_di => spw_di,
339 spw_si => spw_si );
340 end generate;
341 recvfront_sel1: if rximpl = impl_fast generate
342 recvfront_fast_inst: spwrecvfront_fast
343 generic map (
344 rxchunk => rxchunk )
345 port map (
346 clk => clk,
347 rxclk => rxclk,
348 rxen => recv_rxen,
349 inact => recv_inact,
350 inbvalid => recv_inbvalid,
351 inbits => recv_inbits,
352 spw_di => spw_di,
353 spw_si => spw_si );
354 end generate;
355
356 -- Instantiate RX memory.
357 rxmem: spwram
358 generic map (
359 abits => rxfifosize_bits,
360 dbits => 9 )
361 port map (
362 rclk => clk,
363 wclk => clk,
364 ren => '1',
365 raddr => s_rxfifo_raddr,
366 rdata => s_rxfifo_rdata,
367 wen => s_rxfifo_wen,
368 waddr => s_rxfifo_waddr,
369 wdata => s_rxfifo_wdata );
370
371 -- Instantiate TX memory.
372 txmem: spwram
373 generic map (
374 abits => txfifosize_bits,
375 dbits => 9 )
376 port map (
377 rclk => clk,
378 wclk => clk,
379 ren => '1',
380 raddr => s_txfifo_raddr,
381 rdata => s_txfifo_rdata,
382 wen => s_txfifo_wen,
383 waddr => s_txfifo_waddr,
384 wdata => s_txfifo_wdata );
385
386 -- Combinatorial process
387 process (r, linko, s_rxfifo_rdata, s_txfifo_rdata, rst, autostart, linkstart, linkdis, txdivcnt, tick_in, ctrl_in, time_in, txwrite, txflag, txdata, rxread) is
388 variable v: regs_type;
389 variable v_tmprxroom: unsigned(rxfifosize_bits-1 downto 0);
390 variable v_tmptxroom: unsigned(txfifosize_bits-1 downto 0);
391 begin
392 v := r;
393 v_tmprxroom := to_unsigned(0, v_tmprxroom'length);
394 v_tmptxroom := to_unsigned(0, v_tmptxroom'length);
395
396 -- Keep track of whether we are sending and/or receiving a packet.
397 if linko.rxchar = '1' then
398 -- got character
399 v.rxpacket := not linko.rxflag;
400 end if;
401 if linko.txack = '1' then
402 -- send character
403 v.txpacket := not s_txfifo_rdata(8);
404 end if;
405
406 -- Update RX fifo pointers.
407 if (rxread = '1') and (r.rxfifo_rvalid = '1') then
408 -- read from fifo
409 v.rxfifo_raddr := std_logic_vector(unsigned(r.rxfifo_raddr) + 1);
410 end if;
411 if r.rxfull = '0' then
412 if (linko.rxchar = '1') or (r.rxeep = '1') then
413 -- write to fifo (received char or pending EEP)
414 v.rxfifo_waddr := std_logic_vector(unsigned(r.rxfifo_waddr) + 1);
415 end if;
416 v.rxeep := '0';
417 end if;
418
419 -- Keep track of whether the RX fifo contains valid data.
420 -- (use new value of rxfifo_raddr)
421 v.rxfifo_rvalid := bool_to_logic(v.rxfifo_raddr /= r.rxfifo_waddr);
422
423 -- Update room in RX fifo (use new value of rxfifo_waddr).
424 v_tmprxroom := unsigned(r.rxfifo_raddr) - unsigned(v.rxfifo_waddr) - 1;
425 v.rxfull := bool_to_logic(v_tmprxroom = 0);
426 v.rxhalff := not v_tmprxroom(v_tmprxroom'high);
427 if v_tmprxroom > 63 then
428 v.rxroom := (others => '1');
429 else
430 v.rxroom := std_logic_vector(v_tmprxroom(5 downto 0));
431 end if;
432
433 -- Update TX fifo pointers.
434 if (r.txfifo_rvalid = '1') and ((linko.txack = '1') or (r.txdiscard = '1')) then
435 -- read from fifo
436 v.txfifo_raddr := std_logic_vector(unsigned(r.txfifo_raddr) + 1);
437 if s_txfifo_rdata(8) = '1' then
438 v.txdiscard := '0'; -- got EOP/EEP, stop discarding data
439 end if;
440 end if;
441 if (r.txfull = '0') and (txwrite = '1') then
442 -- write to fifo
443 v.txfifo_waddr := std_logic_vector(unsigned(r.txfifo_waddr) + 1);
444 end if;
445
446 -- Keep track of whether the TX fifo contains valid data.
447 -- (use new value of txfifo_raddr)
448 v.txfifo_rvalid := bool_to_logic(v.txfifo_raddr /= r.txfifo_waddr);
449
450 -- Update room in TX fifo (use new value of txfifo_waddr).
451 v_tmptxroom := unsigned(r.txfifo_raddr) - unsigned(v.txfifo_waddr) - 1;
452 v.txfull := bool_to_logic(v_tmptxroom = 0);
453 v.txhalff := not v_tmptxroom(v_tmptxroom'high);
454
455 -- If the link is lost, set a flag to discard the current packet.
456 if linko.running = '0' then
457 v.rxeep := v.rxeep or v.rxpacket; -- use new value of rxpacket
458 v.txdiscard := v.txdiscard or v.txpacket; -- use new value of txpacket
459 v.rxpacket := '0';
460 v.txpacket := '0';
461 end if;
462
463 -- Clear the discard flag when the link is explicitly disabled.
464 if linkdis = '1' then
465 v.txdiscard := '0';
466 end if;
467
468 -- Drive control signals to RX fifo.
469 s_rxfifo_raddr <= v.rxfifo_raddr; -- using new value of rxfifo_raddr
470 s_rxfifo_wen <= (not r.rxfull) and (linko.rxchar or r.rxeep);
471 s_rxfifo_waddr <= r.rxfifo_waddr;
472 if r.rxeep = '1' then
473 s_rxfifo_wdata <= "100000001";
474 else
475 s_rxfifo_wdata <= linko.rxflag & linko.rxdata;
476 end if;
477
478 -- Drive control signals to TX fifo.
479 s_txfifo_raddr <= v.txfifo_raddr; -- using new value of txfifo_raddr
480 s_txfifo_wen <= (not r.txfull) and txwrite;
481 s_txfifo_waddr <= r.txfifo_waddr;
482 s_txfifo_wdata <= txflag & txdata;
483
484 -- Drive inputs to spwlink.
485 linki.autostart <= autostart;
486 linki.linkstart <= linkstart;
487 linki.linkdis <= linkdis;
488 linki.rxroom <= r.rxroom;
489 linki.tick_in <= tick_in;
490 linki.ctrl_in <= ctrl_in;
491 linki.time_in <= time_in;
492 linki.txwrite <= r.txfifo_rvalid and not r.txdiscard;
493 linki.txflag <= s_txfifo_rdata(8);
494 linki.txdata <= s_txfifo_rdata(7 downto 0);
495
496 -- Drive divcnt input to spwxmit.
497 if linko.running = '1' then
498 xmit_divcnt <= txdivcnt;
499 else
500 xmit_divcnt <= default_divcnt;
501 end if;
502
503 -- Drive outputs.
504 txrdy <= not r.txfull;
505 txhalff <= r.txhalff;
506 tick_out <= linko.tick_out;
507 ctrl_out <= linko.ctrl_out;
508 time_out <= linko.time_out;
509 rxvalid <= r.rxfifo_rvalid;
510 rxhalff <= r.rxhalff;
511 rxflag <= s_rxfifo_rdata(8);
512 rxdata <= s_rxfifo_rdata(7 downto 0);
513 started <= linko.started;
514 connecting <= linko.connecting;
515 running <= linko.running;
516 errdisc <= linko.errdisc;
517 errpar <= linko.errpar;
518 erresc <= linko.erresc;
519 errcred <= linko.errcred;
520
521 -- Reset.
522 if rst = '1' then
523 v.rxpacket := '0';
524 v.rxeep := '0';
525 v.txpacket := '0';
526 v.txdiscard := '0';
527 v.rxfifo_raddr := (others => '0');
528 v.rxfifo_waddr := (others => '0');
529 v.txfifo_raddr := (others => '0');
530 v.txfifo_waddr := (others => '0');
531 v.rxfifo_rvalid := '0';
532 v.txfifo_rvalid := '0';
533 end if;
534
535 -- Update registers.
536 rin <= v;
537 end process;
538
539 -- Update registers.
540 process (clk) is
541 begin
542 if rising_edge(clk) then
543 r <= rin;
544 end if;
545 end process;
546
547 end architecture spwstream_arch;
@@ -0,0 +1,249
1 --
2 -- SpaceWire Transmitter
3 --
4 -- This entity translates outgoing characters and tokens into
5 -- data-strobe signalling.
6 --
7
8 library ieee;
9 use ieee.std_logic_1164.all;
10 use ieee.numeric_std.all;
11 use work.spwpkg.all;
12
13 entity spwxmit is
14
15 port (
16 -- System clock.
17 clk: in std_logic;
18
19 -- Synchronous reset (active-high).
20 rst: in std_logic;
21
22 -- Scaling factor minus 1, used to scale the system clock into the
23 -- transmission bit rate. The system clock is divided by
24 -- (unsigned(divcnt) + 1). Changing this signal will immediately
25 -- change the transmission rate.
26 divcnt: in std_logic_vector(7 downto 0);
27
28 -- Input signals from spwlink.
29 xmiti: in spw_xmit_in_type;
30
31 -- Output signals to spwlink.
32 xmito: out spw_xmit_out_type;
33
34 -- Data Out signal to SpaceWire bus.
35 spw_do: out std_logic;
36
37 -- Strobe Out signal to SpaceWire bus.
38 spw_so: out std_logic
39 );
40
41 end entity spwxmit;
42
43 architecture spwxmit_arch of spwxmit is
44
45 -- Registers
46 type regs_type is record
47 -- tx clock
48 txclken: std_ulogic; -- high if a bit must be transmitted
49 txclkcnt: unsigned(7 downto 0);
50 -- output shift register
51 bitshift: std_logic_vector(12 downto 0);
52 bitcnt: unsigned(3 downto 0);
53 -- output signals
54 out_data: std_ulogic;
55 out_strobe: std_ulogic;
56 -- parity flag
57 parity: std_ulogic;
58 -- pending time tick
59 pend_tick: std_ulogic;
60 pend_time: std_logic_vector(7 downto 0);
61 -- transmitter mode
62 allow_fct: std_ulogic; -- allowed to send FCTs
63 allow_char: std_ulogic; -- allowed to send data and time
64 sent_null: std_ulogic; -- sent at least one NULL token
65 sent_fct: std_ulogic; -- sent at least one FCT token
66 end record;
67
68 -- Initial state
69 constant regs_reset: regs_type := (
70 txclken => '0',
71 txclkcnt => "00000000",
72 bitshift => (others => '0'),
73 bitcnt => "0000",
74 out_data => '0',
75 out_strobe => '0',
76 parity => '0',
77 pend_tick => '0',
78 pend_time => (others => '0'),
79 allow_fct => '0',
80 allow_char => '0',
81 sent_null => '0',
82 sent_fct => '0' );
83
84 -- Registers
85 signal r: regs_type := regs_reset;
86 signal rin: regs_type;
87
88 begin
89
90 -- Combinatorial process
91 process (r, rst, divcnt, xmiti) is
92 variable v: regs_type;
93 begin
94 v := r;
95
96 -- Generate TX clock.
97 if r.txclkcnt = 0 then
98 v.txclkcnt := unsigned(divcnt);
99 v.txclken := '1';
100 else
101 v.txclkcnt := r.txclkcnt - 1;
102 v.txclken := '0';
103 end if;
104
105 if xmiti.txen = '0' then
106
107 -- Transmitter disabled; reset state.
108 v.bitcnt := "0000";
109 v.parity := '0';
110 v.pend_tick := '0';
111 v.allow_fct := '0';
112 v.allow_char := '0';
113 v.sent_null := '0';
114 v.sent_fct := '0';
115
116 -- Gentle reset of spacewire bus signals
117 if r.txclken = '1' then
118 v.out_data := r.out_data and r.out_strobe;
119 v.out_strobe := '0';
120 end if;
121
122 else
123 -- Transmitter enabled.
124
125 v.allow_fct := (not xmiti.stnull) and r.sent_null;
126 v.allow_char := (not xmiti.stnull) and r.sent_null and
127 (not xmiti.stfct) and r.sent_fct;
128
129 -- On tick of transmission clock, put next bit on the output.
130 if r.txclken = '1' then
131
132 if r.bitcnt = 0 then
133
134 -- Need to start a new character.
135 if (r.allow_char = '1') and (r.pend_tick = '1') then
136 -- Send Time-Code.
137 v.out_data := r.parity;
138 v.bitshift(12 downto 5) := r.pend_time;
139 v.bitshift(4 downto 0) := "01111";
140 v.bitcnt := to_unsigned(13, v.bitcnt'length);
141 v.parity := '0';
142 v.pend_tick := '0';
143 elsif (r.allow_fct = '1') and (xmiti.fct_in = '1') then
144 -- Send FCT.
145 v.out_data := r.parity;
146 v.bitshift(2 downto 0) := "001";
147 v.bitcnt := to_unsigned(3, v.bitcnt'length);
148 v.parity := '1';
149 v.sent_fct := '1';
150 elsif (r.allow_char = '1') and (xmiti.txwrite = '1') then
151 -- Send N-Char.
152 v.bitshift(0) := xmiti.txflag;
153 v.parity := xmiti.txflag;
154 if xmiti.txflag = '0' then
155 -- Data byte
156 v.out_data := not r.parity;
157 v.bitshift(8 downto 1) := xmiti.txdata;
158 v.bitcnt := to_unsigned(9, v.bitcnt'length);
159 else
160 -- EOP or EEP
161 v.out_data := r.parity;
162 v.bitshift(1) := xmiti.txdata(0);
163 v.bitshift(2) := not xmiti.txdata(0);
164 v.bitcnt := to_unsigned(3, v.bitcnt'length);
165 end if;
166 else
167 -- Send NULL.
168 v.out_data := r.parity;
169 v.bitshift(6 downto 0) := "0010111";
170 v.bitcnt := to_unsigned(7, v.bitcnt'length);
171 v.parity := '0';
172 v.sent_null := '1';
173 end if;
174
175 else
176
177 -- Shift next bit to the output.
178 v.out_data := r.bitshift(0);
179 v.parity := r.parity xor r.bitshift(0);
180 v.bitshift(r.bitshift'high-1 downto 0) := r.bitshift(r.bitshift'high downto 1);
181 v.bitcnt := r.bitcnt - 1;
182
183 end if;
184
185 -- Data-Strobe encoding.
186 v.out_strobe := not (r.out_strobe xor r.out_data xor v.out_data);
187
188 end if;
189
190 -- Store requests for time tick transmission.
191 if xmiti.tick_in = '1' then
192 v.pend_tick := '1';
193 v.pend_time := xmiti.ctrl_in & xmiti.time_in;
194 end if;
195
196 end if;
197
198 -- Synchronous reset
199 if rst = '1' then
200 v := regs_reset;
201 end if;
202
203 -- Drive outputs.
204 -- Note: the outputs are combinatorially dependent on certain inputs.
205
206 -- Set fctack high if (transmitter enabled) AND
207 -- (ready for token) AND (FCTs allowed) AND
208 -- ((characters not allowed) OR (no timecode pending)) AND
209 -- (FCT requested)
210 if (xmiti.txen = '1') and
211 (r.txclken = '1') and (r.bitcnt = 0) and (r.allow_fct = '1') and
212 ((r.allow_char = '0') or (r.pend_tick = '0')) then
213 xmito.fctack <= xmiti.fct_in;
214 else
215 xmito.fctack <= '0';
216 end if;
217
218 -- Set txrdy high if (transmitter enabled) AND
219 -- (ready for token) AND (characters enabled) AND
220 -- (no timecode pending) AND (no FCT requested) AND
221 -- (character requested)
222 if (xmiti.txen = '1') and
223 (r.txclken = '1') and (r.bitcnt = 0) and (r.allow_char = '1') and
224 (r.pend_tick = '0') and (xmiti.fct_in = '0') then
225 xmito.txack <= xmiti.txwrite;
226 else
227 xmito.txack <= '0';
228 end if;
229
230 -- Update registers
231 rin <= v;
232 end process;
233
234 -- Synchronous process
235 process (clk) is
236 begin
237 if rising_edge(clk) then
238
239 -- Update registers
240 r <= rin;
241
242 -- Drive spacewire output signals
243 spw_do <= r.out_data;
244 spw_so <= r.out_strobe;
245
246 end if;
247 end process;
248
249 end architecture spwxmit_arch;
This diff has been collapsed as it changes many lines, (721 lines changed) Show them Hide them
@@ -0,0 +1,721
1 --
2 -- SpaceWire Transmitter
3 --
4 -- This entity translates outgoing characters and tokens into
5 -- data-strobe signalling.
6 --
7 -- The output stage is driven by a separate transmission clock "txclk" which
8 -- will typically be faster than the system clock. The actual transmission
9 -- rate is determined by dividing the transmission clock by an integer factor.
10 --
11 -- The code is tuned for implementation on Xilinx Spartan-3.
12 --
13 -- Concept
14 -- -------
15 --
16 -- Logic in the system clock domain generates a stream of tokens to be
17 -- transmitted. These tokens are encoded as instances of the token_type
18 -- record. Tokens are queued in a two-slot FIFO buffer (r.token0 and r.token1)
19 -- with a 1-bit pointer (r.tokmux) pointing to the head of the queue.
20 -- When a token is pushed into the buffer, a flag register is flipped
21 -- (r.sysflip0 and r.sysflip1) to indicate to the txclk domain that the
22 -- buffer slot has been refilled.
23 --
24 -- The txclk domain pulls tokens from the FIFO buffer, flipping flag
25 -- registers (rtx.txflip0 and rtx.txflip1) to indicate to the system clock
26 -- domain that a token has been pulled. When the system clock domain detects
27 -- that a token has been consumed, it refills the buffer slot with a new
28 -- token (assuming that there are tokens waiting to be transmitted).
29 -- Whenever the FIFO buffer is empty, the txclk domain sends NULLs instead.
30 -- This can happen either when there are no tokens to send, or when the
31 -- system clock domain is late to refill the buffer.
32 --
33 -- Details
34 -- -------
35 --
36 -- Logic in the system clock domain accepts transmission requests through
37 -- the external interface of the entity. Pending requests are translated
38 -- into a stream of tokens. The tokens are pushed to the txclk domain through
39 -- the FIFO buffer as described above.
40 --
41 -- The data path through the txclk domain is divided into stages B through F
42 -- in a half-hearted attempt to keep things simple.
43 --
44 -- Stage B takes a token from the FIFO buffer and updates a buffer status
45 -- flag to indicate that the buffer slot needs to be refilled. If the FIFO
46 -- is empty, a NULL is inserted. Stage B is triggered one clock after
47 -- stage E switches to a new token. If the previous token was ESC, stage B
48 -- skips a turn because stage C will already know what to do.
49 --
50 -- Stage C takes a token from stage B and translates it into a bit pattern.
51 -- Time codes and NULL tokens are broken into two separate tokens starting
52 -- with ESC. Stage C is triggered one clock after the shift buffer in
53 -- stage E drops to 3 tokens.
54 --
55 -- Stage D completes the task of translating tokens to bit patterns and
56 -- distinguishes between 10-bit and 4-bit tokens. It is not explicitly
57 -- triggered but simply follows stage C.
58 --
59 -- Stage E is the bit shift register. It shifts when "txclken" is high.
60 -- A one-hot counter keeps track of the number of bits remaining in
61 -- the register. When the register falls empty, it loads a new 10-bit or
62 -- 4-bit pattern as prepared by stage D. Stage E also computes parity.
63 --
64 -- Stage F performs data strobe encoding. When the transmitter is disabled,
65 -- the outputs of stage F fall to zero in a controlled way.
66 --
67 -- To generate the transmission bit clock, the txclk is divided by an
68 -- integer factor (divcnt+1) using an 8-bit down counter. The implementation
69 -- of this counter has become quite complicated in order to meet timing goals.
70 -- The counter consists of 4 blocks of two bits each (txclkcnt), with a
71 -- carry-save concept used between blocks (txclkcy). Detection of terminal
72 -- count (txclkdone) has a pipeline delay of two cycles. Therefore a separate
73 -- concept is used if the initial count is less than 2 (txdivnorm). This is
74 -- all glued together in the final assignment to txclken.
75 --
76 -- The initial count for txclk division (divcnt) comes from the system clock
77 -- domain and thus needs to be synchronized for use in the txclk domain.
78 -- To facilitate this, the system clock domain latches the value of divcnt
79 -- once every 6 sysclk cycles and sets a flag to indicate when the latched
80 -- value can safely be used by the txclk domain.
81 --
82 -- A tricky aspect of the design is the initial state of the txclk logic.
83 -- When the transmitter is enabled (txen goes high), the txclk logic starts
84 -- with the first ESC pattern already set up in stage D, and stage C ready
85 -- to produce the FCT part of the first NULL.
86 --
87 -- The following guidelines are used to get good timing for the txclk domain:
88 -- * The new value of a register depends on at most 4 inputs (single LUT),
89 -- or in a few cases on 5 inputs (two LUTs and F5MUX).
90 -- * Synchronous resets may be used, but only if the reset signal comes
91 -- directly from a register (no logic in set/reset path);
92 -- * Clock enables may be used, but only if the enable signal comes directly
93 -- from a register (no logic in clock enable path).
94 --
95 -- Synchronization issues
96 -- ----------------------
97 --
98 -- There is a two-slot FIFO buffer between the system and txclk domains.
99 -- After the txclk domain pulls a token from the buffer, the system clock
100 -- domain should ideally refill the buffer before the txclk domain again
101 -- tries to pull from the same buffer slot. If the refill occurs late,
102 -- the txclk domain needs to insert a NULL token which is inefficient
103 -- use of bandwidth.
104 --
105 -- Assuming the transmission consists of a stream of data characters,
106 -- 10 bits per character, there are exactly 2*10 bit periods between
107 -- successive reads from the same buffer slot by the txclk logic.
108 --
109 -- The time needed for the system clock logic to refill a buffer slot =
110 -- 1 txclk period (update of rtx.txflipN)
111 -- + 1 txclk period (routing delay between domains)
112 -- + 2 sysclk periods (synchronizer for txflipN)
113 -- + 1 sysclk period (refill buffer slot and update r.sysflipN)
114 -- + 1 txclk period (routing delay between domains)
115 -- + 2 txclk periods (synchronizer for sysflipN)
116 -- = 5 txclk periods + 3 sysclk periods
117 --
118 -- If for example txclk is 4 times as fast as sysclk, this amounts to
119 -- 5 txclk + 3 sysclk = 5 + 3*4 txclk = 17 txclk
120 -- is less than 20 bit periods even at maximum transmission rate, so
121 -- no problem there.
122 --
123 -- This is different when the data stream includes 4-bit tokens.
124 -- See the manual for further comments.
125 --
126 -- Implementation guidelines
127 -- -------------------------
128 --
129 -- To minimize clock skew, IOB flip-flops should be used to drive
130 -- spw_do and spw_so.
131 --
132 -- "txclk" must be at least as fast as the system clock;
133 -- "txclk" does not need to be phase-related to the system clock;
134 -- it is allowed for "txclk" to be equal to "clk".
135 --
136 -- The following timing constraints are needed:
137 -- * PERIOD constraint on the system clock;
138 -- * PERIOD constraint on "txclk";
139 -- * FROM-TO constraint from "txclk" to the system clock, equal to
140 -- one "txclk" period;
141 -- * FROM-TO constraint from the system clock to "txclk", equal to
142 -- one "txclk" period.
143 --
144
145 library ieee;
146 use ieee.std_logic_1164.all;
147 use ieee.numeric_std.all;
148 use work.spwpkg.all;
149
150 entity spwxmit_fast is
151
152 port (
153 -- System clock.
154 clk: in std_logic;
155
156 -- Transmit clock.
157 txclk: in std_logic;
158
159 -- Synchronous reset (active-high)
160 -- Used asynchronously by fast clock domain (must be glitch-free).
161 rst: in std_logic;
162
163 -- Scaling factor minus 1, used to scale the system clock into the
164 -- transmission bit rate. The system clock is divided by
165 -- (unsigned(divcnt) + 1). Changing this signal will immediately
166 -- change the transmission rate.
167 divcnt: in std_logic_vector(7 downto 0);
168
169 -- Input signals from spwlink.
170 xmiti: in spw_xmit_in_type;
171
172 -- Output signals to spwlink.
173 xmito: out spw_xmit_out_type;
174
175 -- Data Out signal to SpaceWire bus.
176 spw_do: out std_logic;
177
178 -- Strobe Out signal to SpaceWire bus.
179 spw_so: out std_logic
180 );
181
182 -- Turn off FSM extraction to avoid synchronization problems.
183 attribute FSM_EXTRACT: string;
184 attribute FSM_EXTRACT of spwxmit_fast: entity is "NO";
185
186 end entity spwxmit_fast;
187
188 architecture spwxmit_fast_arch of spwxmit_fast is
189
190 -- Convert boolean to std_logic.
191 type bool_to_logic_type is array(boolean) of std_ulogic;
192 constant bool_to_logic: bool_to_logic_type := (false => '0', true => '1');
193
194 -- Data records passed between clock domains.
195 type token_type is record
196 tick: std_ulogic; -- send time code
197 fct: std_ulogic; -- send FCT
198 fctpiggy: std_ulogic; -- send FCT and N-char
199 flag: std_ulogic; -- send EOP or EEP
200 char: std_logic_vector(7 downto 0); -- character or time code
201 end record;
202
203 -- Registers in txclk domain
204 type txregs_type is record
205 -- sync to system clock domain
206 txflip0: std_ulogic;
207 txflip1: std_ulogic;
208 -- stage B
209 b_update: std_ulogic;
210 b_mux: std_ulogic;
211 b_txflip: std_ulogic;
212 b_valid: std_ulogic;
213 b_token: token_type;
214 -- stage C
215 c_update: std_ulogic;
216 c_busy: std_ulogic;
217 c_esc: std_ulogic;
218 c_fct: std_ulogic;
219 c_bits: std_logic_vector(8 downto 0);
220 -- stage D
221 d_bits: std_logic_vector(8 downto 0);
222 d_cnt4: std_ulogic;
223 d_cnt10: std_ulogic;
224 -- stage E
225 e_valid: std_ulogic;
226 e_shift: std_logic_vector(9 downto 0);
227 e_count: std_logic_vector(9 downto 0);
228 e_parity: std_ulogic;
229 -- stage F
230 f_spwdo: std_ulogic;
231 f_spwso: std_ulogic;
232 -- tx clock enable logic
233 txclken: std_ulogic;
234 txclkpre: std_ulogic;
235 txclkcnt: std_logic_vector(7 downto 0);
236 txclkcy: std_logic_vector(2 downto 0);
237 txclkdone: std_logic_vector(1 downto 0);
238 txclkdiv: std_logic_vector(7 downto 0);
239 txdivnorm: std_ulogic;
240 end record;
241
242 -- Registers in system clock domain
243 type regs_type is record
244 -- sync status to txclk domain
245 txenreg: std_ulogic;
246 txdivreg: std_logic_vector(7 downto 0);
247 txdivnorm: std_ulogic;
248 txdivtmp: std_logic_vector(1 downto 0);
249 txdivsafe: std_ulogic;
250 -- data stream to txclk domain
251 sysflip0: std_ulogic;
252 sysflip1: std_ulogic;
253 token0: token_type;
254 token1: token_type;
255 tokmux: std_ulogic;
256 -- transmitter management
257 pend_fct: std_ulogic; -- '1' if an outgoing FCT is pending
258 pend_char: std_ulogic; -- '1' if an outgoing N-Char is pending
259 pend_data: std_logic_vector(8 downto 0); -- control flag and data bits of pending char
260 pend_tick: std_ulogic; -- '1' if an outgoing time tick is pending
261 pend_time: std_logic_vector(7 downto 0); -- data bits of pending time tick
262 allow_fct: std_ulogic; -- '1' when allowed to send FCTs
263 allow_char: std_ulogic; -- '1' when allowed to send data and time
264 sent_fct: std_ulogic; -- '1' when at least one FCT token was sent
265 end record;
266
267 -- Initial state of system clock domain
268 constant token_reset: token_type := (
269 tick => '0',
270 fct => '0',
271 fctpiggy => '0',
272 flag => '0',
273 char => (others => '0') );
274 constant regs_reset: regs_type := (
275 txenreg => '0',
276 txdivreg => (others => '0'),
277 txdivnorm => '0',
278 txdivtmp => "00",
279 txdivsafe => '0',
280 sysflip0 => '0',
281 sysflip1 => '0',
282 token0 => token_reset,
283 token1 => token_reset,
284 tokmux => '0',
285 pend_fct => '0',
286 pend_char => '0',
287 pend_data => (others => '0'),
288 pend_tick => '0',
289 pend_time => (others => '0'),
290 allow_fct => '0',
291 allow_char => '0',
292 sent_fct => '0' );
293
294 -- Signals that are re-synchronized from system clock to txclk domain.
295 type synctx_type is record
296 rstn: std_ulogic;
297 sysflip0: std_ulogic;
298 sysflip1: std_ulogic;
299 txen: std_ulogic;
300 txdivsafe: std_ulogic;
301 end record;
302
303 -- Signals that are re-synchronized from txclk to system clock domain.
304 type syncsys_type is record
305 txflip0: std_ulogic;
306 txflip1: std_ulogic;
307 end record;
308
309 -- Registers
310 signal rtx: txregs_type;
311 signal rtxin: txregs_type;
312 signal r: regs_type := regs_reset;
313 signal rin: regs_type;
314
315 -- Synchronized signals after crossing clock domains.
316 signal synctx: synctx_type;
317 signal syncsys: syncsys_type;
318
319 -- Output flip-flops
320 signal s_spwdo: std_logic;
321 signal s_spwso: std_logic;
322
323 -- Force use of IOB flip-flops
324 attribute IOB: string;
325 attribute IOB of s_spwdo: signal is "TRUE";
326 attribute IOB of s_spwso: signal is "TRUE";
327
328 begin
329
330 -- Reset synchronizer for txclk domain.
331 synctx_rst: syncdff
332 port map ( clk => txclk, rst => rst, di => '1', do => synctx.rstn );
333
334 -- Synchronize signals from system clock domain to txclk domain.
335 synctx_sysflip0: syncdff
336 port map ( clk => txclk, rst => rst, di => r.sysflip0, do => synctx.sysflip0 );
337 synctx_sysflip1: syncdff
338 port map ( clk => txclk, rst => rst, di => r.sysflip1, do => synctx.sysflip1 );
339 synctx_txen: syncdff
340 port map ( clk => txclk, rst => rst, di => r.txenreg, do => synctx.txen );
341 synctx_txdivsafe: syncdff
342 port map ( clk => txclk, rst => rst, di => r.txdivsafe, do => synctx.txdivsafe );
343
344 -- Synchronize signals from txclk domain to system clock domain.
345 syncsys_txflip0: syncdff
346 port map ( clk => clk, rst => rst, di => rtx.txflip0, do => syncsys.txflip0 );
347 syncsys_txflip1: syncdff
348 port map ( clk => clk, rst => rst, di => rtx.txflip1, do => syncsys.txflip1 );
349
350 -- Drive SpaceWire output signals
351 spw_do <= s_spwdo;
352 spw_so <= s_spwso;
353
354 -- Combinatorial process
355 process (r, rtx, rst, divcnt, xmiti, synctx, syncsys) is
356 variable v: regs_type;
357 variable vtx: txregs_type;
358 variable v_needtoken: std_ulogic;
359 variable v_havetoken: std_ulogic;
360 variable v_token: token_type;
361 begin
362 v := r;
363 vtx := rtx;
364 v_needtoken := '0';
365 v_havetoken := '0';
366 v_token := token_reset;
367
368 -- ---- FAST CLOCK DOMAIN ----
369
370 -- Stage B: Multiplex tokens from system clock domain.
371 -- Update stage B three bit periods after updating stage C
372 -- (i.e. in time for the next update of stage C).
373 -- Do not update stage B if stage C is indicating that it needs to
374 -- send a second token to complete its task.
375 vtx.b_update := rtx.txclken and rtx.e_count(0) and (not rtx.c_busy);
376 if rtx.b_mux = '0' then
377 vtx.b_txflip := rtx.txflip0;
378 else
379 vtx.b_txflip := rtx.txflip1;
380 end if;
381 if rtx.b_update = '1' then
382 if rtx.b_mux = '0' then
383 -- get token from slot 0
384 vtx.b_valid := synctx.sysflip0 xor rtx.b_txflip;
385 vtx.b_token := r.token0;
386 -- update mux flag if we got a valid token
387 vtx.b_mux := synctx.sysflip0 xor rtx.b_txflip;
388 vtx.txflip0 := synctx.sysflip0;
389 vtx.txflip1 := rtx.txflip1;
390 else
391 -- get token from slot 1
392 vtx.b_valid := synctx.sysflip1 xor rtx.b_txflip;
393 vtx.b_token := r.token1;
394 -- update mux flag if we got a valid token
395 vtx.b_mux := not (synctx.sysflip1 xor rtx.b_txflip);
396 vtx.txflip0 := rtx.txflip0;
397 vtx.txflip1 := synctx.sysflip1;
398 end if;
399 end if;
400
401 -- Stage C: Prepare to transmit EOP, EEP or a data character.
402 vtx.c_update := rtx.txclken and rtx.e_count(3);
403 if rtx.c_update = '1' then
404
405 -- NULL is broken into two tokens: ESC + FCT.
406 -- Time-codes are broken into two tokens: ESC + char.
407
408 -- Enable c_esc on the first pass of a NULL or a time-code.
409 vtx.c_esc := (rtx.b_token.tick or (not rtx.b_valid)) and
410 (not rtx.c_esc);
411
412 -- Enable c_fct on the first pass of an FCT and on
413 -- the second pass of a NULL (also the first pass, but c_esc
414 -- is stronger than c_fct).
415 vtx.c_fct := (rtx.b_token.fct and (not rtx.c_busy)) or
416 (not rtx.b_valid);
417
418 -- Enable c_busy on the first pass of a NULL or a time-code
419 -- or a piggy-backed FCT. This will tell stage B that we are
420 -- not done yet.
421 vtx.c_busy := (rtx.b_token.tick or (not rtx.b_valid) or
422 rtx.b_token.fctpiggy) and (not rtx.c_busy);
423
424 if rtx.b_token.flag = '1' then
425 if rtx.b_token.char(0) = '0' then
426 -- prepare to send EOP
427 vtx.c_bits := "000000101"; -- EOP = P101
428 else
429 -- prepare to send EEP
430 vtx.c_bits := "000000011"; -- EEP = P110
431 end if;
432 else
433 -- prepare to send data char
434 vtx.c_bits := rtx.b_token.char & '0';
435 end if;
436 end if;
437
438 -- Stage D: Prepare to transmit FCT, ESC, or the stuff from stage C.
439 if rtx.c_esc = '1' then
440 -- prepare to send ESC
441 vtx.d_bits := "000000111"; -- ESC = P111
442 vtx.d_cnt4 := '1'; -- 3 bits + implicit parity bit
443 vtx.d_cnt10 := '0';
444 elsif rtx.c_fct = '1' then
445 -- prepare to send FCT
446 vtx.d_bits := "000000001"; -- FCT = P100
447 vtx.d_cnt4 := '1'; -- 3 bits + implicit parity bit
448 vtx.d_cnt10 := '0';
449 else
450 -- send the stuff from stage C.
451 vtx.d_bits := rtx.c_bits;
452 vtx.d_cnt4 := rtx.c_bits(0);
453 vtx.d_cnt10 := not rtx.c_bits(0);
454 end if;
455
456 -- Stage E: Shift register.
457 if rtx.txclken = '1' then
458 if rtx.e_count(0) = '1' then
459 -- reload shift register; output parity bit
460 vtx.e_valid := '1';
461 vtx.e_shift(vtx.e_shift'high downto 1) := rtx.d_bits;
462 vtx.e_shift(0) := not (rtx.e_parity xor rtx.d_bits(0));
463 vtx.e_count := rtx.d_cnt10 & "00000" & rtx.d_cnt4 & "000";
464 vtx.e_parity := rtx.d_bits(0);
465 else
466 -- shift bits to output; update parity bit
467 vtx.e_shift := '0' & rtx.e_shift(rtx.e_shift'high downto 1);
468 vtx.e_count := '0' & rtx.e_count(rtx.e_count'high downto 1);
469 vtx.e_parity := rtx.e_parity xor rtx.e_shift(1);
470 end if;
471 end if;
472
473 -- Stage F: Data/strobe encoding.
474 if rtx.txclken = '1' then
475 if rtx.e_valid = '1' then
476 -- output next data/strobe bits
477 vtx.f_spwdo := rtx.e_shift(0);
478 vtx.f_spwso := not (rtx.e_shift(0) xor rtx.f_spwdo xor rtx.f_spwso);
479 else
480 -- gentle reset of spacewire signals
481 vtx.f_spwdo := rtx.f_spwdo and rtx.f_spwso;
482 vtx.f_spwso := '0';
483 end if;
484 end if;
485
486 -- Generate tx clock enable
487 -- An 8-bit counter decrements on every clock. A txclken pulse is
488 -- produced 2 cycles after the counter reaches value 2. Counter reload
489 -- values of 0 and 1 are handled as special cases.
490 -- count down in blocks of two bits
491 vtx.txclkcnt(1 downto 0) := std_logic_vector(unsigned(rtx.txclkcnt(1 downto 0)) - 1);
492 vtx.txclkcnt(3 downto 2) := std_logic_vector(unsigned(rtx.txclkcnt(3 downto 2)) - unsigned(rtx.txclkcy(0 downto 0)));
493 vtx.txclkcnt(5 downto 4) := std_logic_vector(unsigned(rtx.txclkcnt(5 downto 4)) - unsigned(rtx.txclkcy(1 downto 1)));
494 vtx.txclkcnt(7 downto 6) := std_logic_vector(unsigned(rtx.txclkcnt(7 downto 6)) - unsigned(rtx.txclkcy(2 downto 2)));
495 -- propagate carry in blocks of two bits
496 vtx.txclkcy(0) := bool_to_logic(rtx.txclkcnt(1 downto 0) = "00");
497 vtx.txclkcy(1) := rtx.txclkcy(0) and bool_to_logic(rtx.txclkcnt(3 downto 2) = "00");
498 vtx.txclkcy(2) := rtx.txclkcy(1) and bool_to_logic(rtx.txclkcnt(5 downto 4) = "00");
499 -- detect value 2 in counter
500 vtx.txclkdone(0) := bool_to_logic(rtx.txclkcnt(3 downto 0) = "0010");
501 vtx.txclkdone(1) := bool_to_logic(rtx.txclkcnt(7 downto 4) = "0000");
502 -- trigger txclken
503 vtx.txclken := (rtx.txclkdone(0) and rtx.txclkdone(1)) or rtx.txclkpre;
504 vtx.txclkpre := (not rtx.txdivnorm) and ((not rtx.txclkpre) or (not rtx.txclkdiv(0)));
505 -- reload counter
506 if rtx.txclken = '1' then
507 vtx.txclkcnt := rtx.txclkdiv;
508 vtx.txclkcy := "000";
509 vtx.txclkdone := "00";
510 end if;
511
512 -- Synchronize txclkdiv
513 if synctx.txdivsafe = '1' then
514 vtx.txclkdiv := r.txdivreg;
515 vtx.txdivnorm := r.txdivnorm;
516 end if;
517
518 -- Transmitter disabled.
519 if synctx.txen = '0' then
520 vtx.txflip0 := '0';
521 vtx.txflip1 := '0';
522 vtx.b_update := '0';
523 vtx.b_mux := '0';
524 vtx.b_valid := '0';
525 vtx.c_update := '0';
526 vtx.c_busy := '1';
527 vtx.c_esc := '1'; -- need to send 2nd part of NULL
528 vtx.c_fct := '1';
529 vtx.d_bits := "000000111"; -- ESC = P111
530 vtx.d_cnt4 := '1'; -- 3 bits + implicit parity bit
531 vtx.d_cnt10 := '0';
532 vtx.e_valid := '0';
533 vtx.e_parity := '0';
534 vtx.e_count := (0 => '1', others => '0');
535 end if;
536
537 -- Reset.
538 if synctx.rstn = '0' then
539 vtx.f_spwdo := '0';
540 vtx.f_spwso := '0';
541 vtx.txclken := '0';
542 vtx.txclkpre := '1';
543 vtx.txclkcnt := (others => '0');
544 vtx.txclkdiv := (others => '0');
545 vtx.txdivnorm := '0';
546 end if;
547
548 -- ---- SYSTEM CLOCK DOMAIN ----
549
550 -- Hold divcnt and txen for use by txclk domain.
551 v.txdivtmp := std_logic_vector(unsigned(r.txdivtmp) - 1);
552 if r.txdivtmp = "00" then
553 if r.txdivsafe = '0' then
554 -- Latch the current value of divcnt and txen.
555 v.txdivsafe := '1';
556 v.txdivtmp := "01";
557 v.txdivreg := divcnt;
558 if unsigned(divcnt(divcnt'high downto 1)) = 0 then
559 v.txdivnorm := '0';
560 else
561 v.txdivnorm := '1';
562 end if;
563 v.txenreg := xmiti.txen;
564 else
565 -- Drop the txdivsafe flag but keep latched values.
566 v.txdivsafe := '0';
567 end if;
568 end if;
569
570 -- Pass falling edge of txen signal as soon as possible.
571 if xmiti.txen = '0' then
572 v.txenreg := '0';
573 end if;
574
575 -- Store requests for FCT transmission.
576 if xmiti.fct_in = '1' and r.allow_fct = '1' then
577 v.pend_fct := '1';
578 end if;
579
580 if xmiti.txen = '0' then
581
582 -- Transmitter disabled; reset state.
583 v.sysflip0 := '0';
584 v.sysflip1 := '0';
585 v.tokmux := '0';
586 v.pend_fct := '0';
587 v.pend_char := '0';
588 v.pend_tick := '0';
589 v.allow_fct := '0';
590 v.allow_char := '0';
591 v.sent_fct := '0';
592
593 else
594
595 -- Determine if a new token is needed.
596 if r.tokmux = '0' then
597 if r.sysflip0 = syncsys.txflip0 then
598 v_needtoken := '1';
599 end if;
600 else
601 if r.sysflip1 = syncsys.txflip1 then
602 v_needtoken := '1';
603 end if;
604 end if;
605
606 -- Prepare new token.
607 if r.allow_char = '1' and r.pend_tick = '1' then
608 -- prepare to send time code
609 v_token.tick := '1';
610 v_token.fct := '0';
611 v_token.fctpiggy := '0';
612 v_token.flag := '0';
613 v_token.char := r.pend_time;
614 v_havetoken := '1';
615 if v_needtoken = '1' then
616 v.pend_tick := '0';
617 end if;
618 else
619 if r.allow_fct = '1' and (xmiti.fct_in = '1' or r.pend_fct = '1') then
620 -- prepare to send FCT
621 v_token.fct := '1';
622 v_havetoken := '1';
623 if v_needtoken = '1' then
624 v.pend_fct := '0';
625 v.sent_fct := '1';
626 end if;
627 end if;
628 if r.allow_char = '1' and r.pend_char = '1' then
629 -- prepare to send N-Char
630 -- Note: it is possible to send an FCT and an N-Char
631 -- together by enabling the fctpiggy flag.
632 v_token.fctpiggy := v_token.fct;
633 v_token.flag := r.pend_data(8);
634 v_token.char := r.pend_data(7 downto 0);
635 v_havetoken := '1';
636 if v_needtoken = '1' then
637 v.pend_char := '0';
638 end if;
639 end if;
640 end if;
641
642 -- Put new token in slot.
643 if v_havetoken = '1' then
644 if r.tokmux = '0' then
645 if r.sysflip0 = syncsys.txflip0 then
646 v.sysflip0 := not r.sysflip0;
647 v.token0 := v_token;
648 v.tokmux := '1';
649 end if;
650 else
651 if r.sysflip1 = syncsys.txflip1 then
652 v.sysflip1 := not r.sysflip1;
653 v.token1 := v_token;
654 v.tokmux := '0';
655 end if;
656 end if;
657 end if;
658
659 -- Determine whether we are allowed to send FCTs and characters
660 v.allow_fct := not xmiti.stnull;
661 v.allow_char := (not xmiti.stnull) and (not xmiti.stfct) and r.sent_fct;
662
663 -- Store request for data transmission.
664 if xmiti.txwrite = '1' and r.allow_char = '1' and r.pend_char = '0' then
665 v.pend_char := '1';
666 v.pend_data := xmiti.txflag & xmiti.txdata;
667 end if;
668
669 -- Store requests for time tick transmission.
670 if xmiti.tick_in = '1' then
671 v.pend_tick := '1';
672 v.pend_time := xmiti.ctrl_in & xmiti.time_in;
673 end if;
674
675 end if;
676
677 -- Synchronous reset of system clock domain.
678 if rst = '1' then
679 v := regs_reset;
680 end if;
681
682 -- Drive outputs.
683 -- Note: the outputs are combinatorially dependent on certain inputs.
684
685 -- Set fctack high if (FCT requested) and (FCTs allowed) AND
686 -- (no FCT pending)
687 xmito.fctack <= xmiti.fct_in and xmiti.txen and r.allow_fct and
688 (not r.pend_fct);
689
690 -- Set txrdy high if (character requested) AND (characters allowed) AND
691 -- (no character pending)
692 xmito.txack <= xmiti.txwrite and xmiti.txen and r.allow_char and
693 (not r.pend_char);
694
695 -- Update registers.
696 rin <= v;
697 rtxin <= vtx;
698 end process;
699
700 -- Synchronous process in txclk domain
701 process (txclk) is
702 begin
703 if rising_edge(txclk) then
704 -- drive spacewire output signals
705 s_spwdo <= rtx.f_spwdo;
706 s_spwso <= rtx.f_spwso;
707 -- update registers
708 rtx <= rtxin;
709 end if;
710 end process;
711
712 -- Synchronous process in system clock domain
713 process (clk) is
714 begin
715 if rising_edge(clk) then
716 -- update registers
717 r <= rin;
718 end if;
719 end process;
720
721 end architecture spwxmit_fast_arch;
@@ -0,0 +1,446
1 --
2 -- Test application for spwstream.
3 --
4 -- This entity implements one spwstream instance with SpaceWire signals
5 -- routed to external ports. The SpaceWire port is assumed to be looped back
6 -- to itself externally, either directly (tx pins wired to rx pins) or
7 -- through a remote SpaceWire device which is programmed to echo anything
8 -- it receives.
9 --
10 -- This entity submits a series of test patterns to the transmit side of
11 -- spwstream. At the same time it monitors the receive side of spwstream
12 -- and verifies that received data matches the transmitted data pattern.
13 --
14 -- Link mode and tx bit rate may be programmed through digital inputs
15 -- (presumably connected to switches or buttons). Link state and progress of
16 -- the test are reported through digital outputs (presumably connected to
17 -- LEDs).
18 --
19 -- Note: there is no check on the integrity of the first packet received
20 -- after the link goes up.
21 --
22
23 library ieee;
24 use ieee.std_logic_1164.all;
25 use ieee.numeric_std.all;
26 use work.spwpkg.all;
27
28 entity streamtest is
29
30 generic (
31 -- System clock frequency in Hz.
32 sysfreq: real;
33
34 -- txclk frequency in Hz (if tximpl = impl_fast).
35 txclkfreq: real;
36
37 -- 2-log of division factor from system clock freq to timecode freq.
38 tickdiv: integer range 12 to 24 := 20;
39
40 -- Receiver front-end implementation.
41 rximpl: spw_implementation_type := impl_generic;
42
43 -- Maximum number of bits received per system clock (impl_fast only).
44 rxchunk: integer range 1 to 4 := 1;
45
46 -- Transmitter implementation.
47 tximpl: spw_implementation_type := impl_generic;
48
49 -- Size of receive FIFO.
50 rxfifosize_bits: integer range 6 to 14 := 11;
51
52 -- Size of transmit FIFO.
53 txfifosize_bits: integer range 2 to 14 := 11 );
54
55 port (
56 -- System clock.
57 clk: in std_logic;
58
59 -- Receiver sample clock (only for impl_fast).
60 rxclk: in std_logic;
61
62 -- Transmit clock (only for impl_fast).
63 txclk: in std_logic;
64
65 -- Synchronous reset (active-high).
66 rst: in std_logic;
67
68 -- Enables spontaneous link start.
69 linkstart: in std_logic;
70
71 -- Enables automatic link start on receipt of a NULL token.
72 autostart: in std_logic;
73
74 -- Do not start link and/or disconnect current link.
75 linkdisable: in std_logic;
76
77 -- Enable sending test patterns to spwstream.
78 senddata: in std_logic;
79
80 -- Enable sending time codes to spwstream.
81 sendtick: in std_logic;
82
83 -- Scaling factor minus 1 for TX bitrate.
84 txdivcnt: in std_logic_vector(7 downto 0);
85
86 -- Link in state Started.
87 linkstarted: out std_logic;
88
89 -- Link in state Connecting.
90 linkconnecting: out std_logic;
91
92 -- Link in state Run.
93 linkrun: out std_logic;
94
95 -- Link error (one cycle pulse, not directly suitable for LED)
96 linkerror: out std_logic;
97
98 -- High when taking a byte from the receive FIFO.
99 gotdata: out std_logic;
100
101 -- Incorrect or unexpected data received (sticky).
102 dataerror: out std_logic;
103
104 -- Incorrect or unexpected time code received (sticky).
105 tickerror: out std_logic;
106
107 -- SpaceWire signals.
108 spw_di: in std_logic;
109 spw_si: in std_logic;
110 spw_do: out std_logic;
111 spw_so: out std_logic );
112
113 end entity streamtest;
114
115 architecture streamtest_arch of streamtest is
116
117 -- Update 16-bit maximum length LFSR by 8 steps
118 function lfsr16(x: in std_logic_vector) return std_logic_vector is
119 variable y: std_logic_vector(15 downto 0);
120 begin
121 -- poly = x^16 + x^14 + x^13 + x^11 + 1
122 -- tap positions = x(0), x(2), x(3), x(5)
123 y(7 downto 0) := x(15 downto 8);
124 y(15 downto 8) := x(7 downto 0) xor x(9 downto 2) xor x(10 downto 3) xor x(12 downto 5);
125 return y;
126 end function;
127
128 -- Sending side state.
129 type tx_state_type is ( txst_idle, txst_prepare, txst_data );
130
131 -- Receiving side state.
132 type rx_state_type is ( rxst_idle, rxst_data );
133
134 -- Registers.
135 type regs_type is record
136 tx_state: tx_state_type;
137 tx_timecnt: std_logic_vector((tickdiv-1) downto 0);
138 tx_quietcnt: std_logic_vector(15 downto 0);
139 tx_pktlen: std_logic_vector(15 downto 0);
140 tx_lfsr: std_logic_vector(15 downto 0);
141 tx_enabledata: std_ulogic;
142 rx_state: rx_state_type;
143 rx_quietcnt: std_logic_vector(15 downto 0);
144 rx_enabledata: std_ulogic;
145 rx_gottick: std_ulogic;
146 rx_expecttick: std_ulogic;
147 rx_expectglitch: unsigned(5 downto 0);
148 rx_badpacket: std_ulogic;
149 rx_pktlen: std_logic_vector(15 downto 0);
150 rx_prev: std_logic_vector(15 downto 0);
151 rx_lfsr: std_logic_vector(15 downto 0);
152 running: std_ulogic;
153 tick_in: std_ulogic;
154 time_in: std_logic_vector(5 downto 0);
155 txwrite: std_ulogic;
156 txflag: std_ulogic;
157 txdata: std_logic_vector(7 downto 0);
158 rxread: std_ulogic;
159 gotdata: std_ulogic;
160 dataerror: std_ulogic;
161 tickerror: std_ulogic;
162 end record;
163
164 -- Reset state.
165 constant regs_reset: regs_type := (
166 tx_state => txst_idle,
167 tx_timecnt => (others => '0'),
168 tx_quietcnt => (others => '0'),
169 tx_pktlen => (others => '0'),
170 tx_lfsr => (1 => '1', others => '0'),
171 tx_enabledata => '0',
172 rx_state => rxst_idle,
173 rx_quietcnt => (others => '0'),
174 rx_enabledata => '0',
175 rx_gottick => '0',
176 rx_expecttick => '0',
177 rx_expectglitch => "000001",
178 rx_badpacket => '0',
179 rx_pktlen => (others => '0'),
180 rx_prev => (others => '0'),
181 rx_lfsr => (others => '0'),
182 running => '0',
183 tick_in => '0',
184 time_in => (others => '0'),
185 txwrite => '0',
186 txflag => '0',
187 txdata => (others => '0'),
188 rxread => '0',
189 gotdata => '0',
190 dataerror => '0',
191 tickerror => '0' );
192
193 signal r: regs_type := regs_reset;
194 signal rin: regs_type;
195
196 -- Interface signals.
197 signal s_txrdy: std_logic;
198 signal s_tickout: std_logic;
199 signal s_timeout: std_logic_vector(5 downto 0);
200 signal s_rxvalid: std_logic;
201 signal s_rxflag: std_logic;
202 signal s_rxdata: std_logic_vector(7 downto 0);
203 signal s_running: std_logic;
204 signal s_errdisc: std_logic;
205 signal s_errpar: std_logic;
206 signal s_erresc: std_logic;
207 signal s_errcred: std_logic;
208
209 begin
210
211 -- spwstream instance
212 spwstream_inst: spwstream
213 generic map (
214 sysfreq => sysfreq,
215 txclkfreq => txclkfreq,
216 rximpl => rximpl,
217 rxchunk => rxchunk,
218 tximpl => tximpl,
219 rxfifosize_bits => rxfifosize_bits,
220 txfifosize_bits => txfifosize_bits )
221 port map (
222 clk => clk,
223 rxclk => rxclk,
224 txclk => txclk,
225 rst => rst,
226 autostart => autostart,
227 linkstart => linkstart,
228 linkdis => linkdisable,
229 txdivcnt => txdivcnt,
230 tick_in => r.tick_in,
231 ctrl_in => (others => '0'),
232 time_in => r.time_in,
233 txwrite => r.txwrite,
234 txflag => r.txflag,
235 txdata => r.txdata,
236 txrdy => s_txrdy,
237 txhalff => open,
238 tick_out => s_tickout,
239 ctrl_out => open,
240 time_out => s_timeout,
241 rxvalid => s_rxvalid,
242 rxhalff => open,
243 rxflag => s_rxflag,
244 rxdata => s_rxdata,
245 rxread => r.rxread,
246 started => linkstarted,
247 connecting => linkconnecting,
248 running => s_running,
249 errdisc => s_errdisc,
250 errpar => s_errpar,
251 erresc => s_erresc,
252 errcred => s_errcred,
253 spw_di => spw_di,
254 spw_si => spw_si,
255 spw_do => spw_do,
256 spw_so => spw_so );
257
258 -- Drive status indications.
259 linkrun <= s_running;
260 linkerror <= s_errdisc or s_errpar or s_erresc or s_errcred;
261 gotdata <= r.gotdata;
262 dataerror <= r.dataerror;
263 tickerror <= r.tickerror;
264
265 process (r, rst, senddata, sendtick, s_txrdy, s_tickout, s_timeout, s_rxvalid, s_rxflag, s_rxdata, s_running) is
266 variable v: regs_type;
267 begin
268 v := r;
269
270 -- Initiate timecode transmissions.
271 v.tx_timecnt := std_logic_vector(unsigned(r.tx_timecnt) + 1);
272 if unsigned(v.tx_timecnt) = 0 then
273 v.tick_in := sendtick;
274 else
275 v.tick_in := '0';
276 end if;
277 if r.tick_in = '1' then
278 v.time_in := std_logic_vector(unsigned(r.time_in) + 1);
279 v.rx_expecttick := '1';
280 v.rx_gottick := '0';
281 end if;
282
283 -- Turn data generator on/off at regular intervals.
284 v.tx_quietcnt := std_logic_vector(unsigned(r.tx_quietcnt) + 1);
285 if unsigned(r.tx_quietcnt) = 61000 then
286 v.tx_quietcnt := (others => '0');
287 end if;
288 v.tx_enabledata := senddata and (not r.tx_quietcnt(15));
289
290 -- Generate data packets.
291 case r.tx_state is
292 when txst_idle =>
293 -- generate packet length
294 v.tx_state := txst_prepare;
295 v.tx_pktlen := r.tx_lfsr;
296 v.txwrite := '0';
297 v.tx_lfsr := lfsr16(r.tx_lfsr);
298 when txst_prepare =>
299 -- generate first byte of packet
300 v.tx_state := txst_data;
301 v.txwrite := r.tx_enabledata;
302 v.txflag := '0';
303 v.txdata := r.tx_lfsr(15 downto 8);
304 v.tx_lfsr := lfsr16(r.tx_lfsr);
305 when txst_data =>
306 -- generate data bytes and EOP
307 v.txwrite := r.tx_enabledata;
308 if r.txwrite = '1' and s_txrdy = '1' then
309 -- just sent one byte
310 v.tx_pktlen := std_logic_vector(unsigned(r.tx_pktlen) - 1);
311 if unsigned(r.tx_pktlen) = 0 then
312 -- done with packet
313 v.tx_state := txst_idle;
314 v.txwrite := '0';
315 elsif unsigned(r.tx_pktlen) = 1 then
316 -- generate EOP
317 v.txwrite := r.tx_enabledata;
318 v.txflag := '1';
319 v.txdata := (others => '0');
320 v.tx_lfsr := lfsr16(r.tx_lfsr);
321 else
322 -- generate next data byte
323 v.txwrite := r.tx_enabledata;
324 v.txflag := '0';
325 v.txdata := r.tx_lfsr(15 downto 8);
326 v.tx_lfsr := lfsr16(r.tx_lfsr);
327 end if;
328 end if;
329 end case;
330
331 -- Blink light when receiving data.
332 v.gotdata := s_rxvalid and r.rxread;
333
334 -- Detect missing timecodes.
335 if r.tick_in = '1' and r.rx_expecttick = '1' then
336 -- This is bad; a new timecode is being generated while
337 -- we have not even received the previous one yet.
338 v.tickerror := '1';
339 end if;
340
341 -- Receive and check incoming timecodes.
342 if s_tickout = '1' then
343 if unsigned(s_timeout) + 1 /= unsigned(r.time_in) then
344 -- Received time code does not match last transmitted code.
345 v.tickerror := '1';
346 end if;
347 if r.rx_gottick = '1' then
348 -- Already received the last transmitted time code.
349 v.tickerror := '1';
350 end if;
351 v.rx_expecttick := '0';
352 v.rx_gottick := '1';
353 end if;
354
355 -- Turn data receiving on/off at regular intervals
356 v.rx_quietcnt := std_logic_vector(unsigned(r.rx_quietcnt) + 1);
357 if unsigned(r.rx_quietcnt) = 55000 then
358 v.rx_quietcnt := (others => '0');
359 end if;
360 v.rx_enabledata := not r.rx_quietcnt(15);
361
362 case r.rx_state is
363 when rxst_idle =>
364 -- get expected packet length
365 v.rx_state := rxst_data;
366 v.rx_pktlen := r.rx_lfsr;
367 v.rx_lfsr := lfsr16(r.rx_lfsr);
368 v.rx_prev := (others => '0');
369 when rxst_data =>
370 v.rxread := r.rx_enabledata;
371 if r.rxread = '1' and s_rxvalid = '1' then
372 -- got next byte
373 v.rx_pktlen := std_logic_vector(unsigned(r.rx_pktlen) - 1);
374 v.rx_prev := s_rxdata & r.rx_prev(15 downto 8);
375 if s_rxflag = '1' then
376 -- got EOP or EEP
377 v.rxread := '0';
378 v.rx_state := rxst_idle;
379 if s_rxdata = "00000000" then
380 -- got EOP
381 if unsigned(r.rx_pktlen) /= 0 then
382 -- unexpected EOP
383 v.rx_badpacket := '1';
384 end if;
385 -- count errors against expected glitches
386 if v.rx_badpacket = '1' then
387 -- got glitch
388 if r.rx_expectglitch = 0 then
389 v.dataerror := '1';
390 else
391 v.rx_expectglitch := r.rx_expectglitch - 1;
392 end if;
393 end if;
394 -- resynchronize LFSR
395 v.rx_lfsr := lfsr16(lfsr16(r.rx_prev));
396 else
397 -- got EEP
398 v.rx_badpacket := '1';
399 end if;
400 v.rx_badpacket := '0';
401 else
402 -- got next byte
403 v.rx_lfsr := lfsr16(r.rx_lfsr);
404 if unsigned(r.rx_pktlen) = 0 then
405 -- missing EOP
406 v.rx_badpacket := '1';
407 end if;
408 if s_rxdata /= r.rx_lfsr(15 downto 8) then
409 -- bad data
410 v.rx_badpacket := '1';
411 end if;
412 end if;
413 end if;
414 end case;
415
416 -- If the link goes away, we should expect inconsistency on the receiving side.
417 v.running := s_running;
418 if r.running = '1' and s_running = '0' then
419 if r.rx_expectglitch /= "111111" then
420 v.rx_expectglitch := r.rx_expectglitch + 1;
421 end if;
422 end if;
423
424 -- If there is no link, we should not expect to receive time codes.
425 if s_running = '0' then
426 v.rx_expecttick := '0';
427 end if;
428
429 -- Synchronous reset.
430 if rst = '1' then
431 v := regs_reset;
432 end if;
433
434 -- Update registers.
435 rin <= v;
436 end process;
437
438 -- Update registers.
439 process (clk) is
440 begin
441 if rising_edge(clk) then
442 r <= rin;
443 end if;
444 end process;
445
446 end architecture streamtest_arch;
@@ -0,0 +1,70
1 --
2 -- Double flip-flop synchronizer.
3 --
4 -- This entity is used to safely capture asynchronous signals.
5 --
6 -- An implementation may assign additional constraints to this entity
7 -- in order to reduce the probability of meta-stability issues.
8 -- For example, an extra tight timing constraint could be placed on
9 -- the data path from syncdff_ff1 to syncdff_ff2 to ensure that
10 -- meta-stability of ff1 is resolved before ff2 captures the signal.
11 --
12
13 library ieee;
14 use ieee.std_logic_1164.all;
15
16 entity syncdff is
17
18 port (
19 clk: in std_logic; -- clock (destination domain)
20 rst: in std_logic; -- asynchronous reset, active-high
21 di: in std_logic; -- input data
22 do: out std_logic -- output data
23 );
24
25 -- Turn off register replication in XST.
26 attribute REGISTER_DUPLICATION: string;
27 attribute REGISTER_DUPLICATION of syncdff: entity is "NO";
28
29 end entity syncdff;
30
31 architecture syncdff_arch of syncdff is
32
33 -- flip-flops
34 signal syncdff_ff1: std_ulogic := '0';
35 signal syncdff_ff2: std_ulogic := '0';
36
37 -- Turn of shift-register extraction in XST.
38 attribute SHIFT_EXTRACT: string;
39 attribute SHIFT_EXTRACT of syncdff_ff1: signal is "NO";
40 attribute SHIFT_EXTRACT of syncdff_ff2: signal is "NO";
41
42 -- Tell XST to place both flip-flops in the same slice.
43 attribute RLOC: string;
44 attribute RLOC of syncdff_ff1: signal is "X0Y0";
45 attribute RLOC of syncdff_ff2: signal is "X0Y0";
46
47 -- Tell XST to keep the flip-flop net names to be used in timing constraints.
48 attribute KEEP: string;
49 attribute KEEP of syncdff_ff1: signal is "SOFT";
50 attribute KEEP of syncdff_ff2: signal is "SOFT";
51
52 begin
53
54 -- second flip-flop drives the output signal
55 do <= syncdff_ff2;
56
57 process (clk, rst) is
58 begin
59 if rst = '1' then
60 -- asynchronous reset
61 syncdff_ff1 <= '0';
62 syncdff_ff2 <= '0';
63 elsif rising_edge(clk) then
64 -- data synchronization
65 syncdff_ff1 <= di;
66 syncdff_ff2 <= syncdff_ff1;
67 end if;
68 end process;
69
70 end architecture syncdff_arch;
@@ -0,0 +1,84
1 VHDLIB=../..
2 SCRIPTSDIR=$(VHDLIB)/scripts/
3 GRLIB := $(shell sh $(VHDLIB)/scripts/lpp_relpath.sh)
4 TOP=testbench
5 BOARD=LFR-EQM
6 include $(VHDLIB)/boards/$(BOARD)/Makefile_RTAX.inc
7 DEVICE=$(PART)-$(PACKAGE)$(SPEED)
8 UCF=
9 QSF=
10 EFFORT=high
11 XSTOPT=
12 SYNPOPT=
13 VHDLSYNFILES=
14 VHDLSIMFILES= tb.vhd $(VHDLIB)/boards/designs/LFR-EQM-RTAX/LFR-EQM.vhd
15 SIMTOP=testbench
16 CLEAN=soft-clean
17
18 TECHLIBS = axcelerator
19
20 LIBSKIP = core1553bbc core1553brm core1553brt gr1553 corePCIF \
21 tmtc openchip hynix ihp gleichmann micron usbhc opencores fmf ftlib gsi
22
23 DIRSKIP = b1553 pcif leon2 leon3v3 leon2ft crypto satcan ddr usb ata i2c \
24 pci grusbhc haps slink ascs can pwm greth coremp7 spi ac97 srmmu atf \
25 grlfpc \
26 ./dsp/lpp_fft_rtax \
27 ./amba_lcd_16x2_ctrlr \
28 ./general_purpose/lpp_AMR \
29 ./general_purpose/lpp_balise \
30 ./general_purpose/lpp_delay \
31 ./lpp_bootloader \
32 ./lfr_management \
33 ./lpp_sim/CY7C1061DV33 \
34 ./lpp_cna \
35 ./lpp_uart \
36 ./lpp_usb \
37 ./dsp/lpp_fft \
38 ./lpp_leon3_soc \
39 ./lpp_debug_lfr
40
41 FILESKIP = i2cmst.vhd \
42 APB_MULTI_DIODE.vhd \
43 APB_MULTI_DIODE.vhd \
44 Top_MatrixSpec.vhd \
45 APB_FFT.vhd \
46 lpp_lfr_ms_FFT.vhd \
47 lpp_lfr_apbreg.vhd \
48 CoreFFT.vhd \
49 lpp_lfr_ms.vhd \
50 lpp_lfr_sim_pkg.vhd \
51 mtie_maps.vhd \
52 ftsrctrlc.vhd \
53 ftsdctrl.vhd \
54 ftsrctrl8.vhd \
55 ftmctrl.vhd \
56 ftsdctrl64.vhd \
57 ftahbram.vhd \
58 ftahbram2.vhd \
59 sramft.vhd \
60 nandfctrlx.vhd
61
62 include $(GRLIB)/bin/Makefile
63 include $(GRLIB)/software/leon3/Makefile
64
65 ################## project specific targets ##########################
66 distclean:myclean
67 vsim:cp_for_vsim
68
69 myclean:
70 rm -f input.txt output_fx.txt *.log
71 rm -rf ./2016*
72
73 generate :
74 python ./generate.py
75
76 cp_for_vsim: generate
77 cp ./input.txt simulation/
78
79 archivate:
80 xonsh ./archivate.xsh
81
82 test: | generate ghdl ghdl-run archivate
83
84
@@ -0,0 +1,254
1
2 LIBRARY ieee;
3 USE ieee.std_logic_1164.ALL;
4 USE ieee.numeric_std.ALL;
5 USE IEEE.std_logic_signed.ALL;
6 USE IEEE.MATH_real.ALL;
7
8 LIBRARY techmap;
9 USE techmap.gencomp.ALL;
10
11 LIBRARY std;
12 USE std.textio.ALL;
13
14 LIBRARY lpp;
15 USE lpp.iir_filter.ALL;
16 USE lpp.lpp_ad_conv.ALL;
17 USE lpp.FILTERcfg.ALL;
18 USE lpp.lpp_lfr_filter_coeff.ALL;
19 USE lpp.general_purpose.ALL;
20 USE lpp.data_type_pkg.ALL;
21 USE lpp.lpp_lfr_pkg.ALL;
22 USE lpp.general_purpose.ALL;
23 USE lpp.lpp_sim_pkg.ALL;
24 USE lpp.lpp_waveform_pkg.ALL;
25
26 ENTITY testbench IS
27 GENERIC(
28 tech : INTEGER := 0; --axcel,0
29 Mem_use : INTEGER := use_CEL --use_RAM,use_CEL
30 );
31 END;
32
33 ARCHITECTURE behav OF testbench IS
34
35
36 COMPONENT LFR_EQM IS
37 GENERIC (
38 Mem_use : INTEGER := use_RAM;
39 USE_BOOTLOADER : INTEGER := 0;
40 USE_ADCDRIVER : INTEGER := 1;
41 tech : INTEGER := inferred;
42 tech_leon : INTEGER := inferred;
43 DEBUG_FORCE_DATA_DMA : INTEGER := 0;
44 USE_DEBUG_VECTOR : INTEGER := 0
45 );
46
47 PORT (
48 clk50MHz : IN STD_ULOGIC;
49 clk49_152MHz : IN STD_ULOGIC;
50 reset : IN STD_ULOGIC;
51
52 TAG : INOUT STD_LOGIC_VECTOR(9 DOWNTO 1);
53
54 address : OUT STD_LOGIC_VECTOR(18 DOWNTO 0);
55 data : INOUT STD_LOGIC_VECTOR(31 DOWNTO 0);
56
57 nSRAM_MBE : INOUT STD_LOGIC; -- new
58 nSRAM_E1 : OUT STD_LOGIC; -- new
59 nSRAM_E2 : OUT STD_LOGIC; -- new
60 -- nSRAM_SCRUB : OUT STD_LOGIC; -- new
61 nSRAM_W : OUT STD_LOGIC; -- new
62 nSRAM_G : OUT STD_LOGIC; -- new
63 nSRAM_BUSY : IN STD_LOGIC; -- new
64 -- SPW --------------------------------------------------------------------
65 spw1_en : OUT STD_LOGIC; -- new
66 spw1_din : IN STD_LOGIC;
67 spw1_sin : IN STD_LOGIC;
68 spw1_dout : OUT STD_LOGIC;
69 spw1_sout : OUT STD_LOGIC;
70 spw2_en : OUT STD_LOGIC; -- new
71 spw2_din : IN STD_LOGIC;
72 spw2_sin : IN STD_LOGIC;
73 spw2_dout : OUT STD_LOGIC;
74 spw2_sout : OUT STD_LOGIC;
75 -- ADC --------------------------------------------------------------------
76 bias_fail_sw : OUT STD_LOGIC;
77 ADC_OEB_bar_CH : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
78 ADC_smpclk : OUT STD_LOGIC;
79 ADC_data : IN STD_LOGIC_VECTOR(13 DOWNTO 0);
80 -- DAC --------------------------------------------------------------------
81 DAC_SDO : OUT STD_LOGIC;
82 DAC_SCK : OUT STD_LOGIC;
83 DAC_SYNC : OUT STD_LOGIC;
84 DAC_CAL_EN : OUT STD_LOGIC;
85 -- HK ---------------------------------------------------------------------
86 HK_smpclk : OUT STD_LOGIC;
87 ADC_OEB_bar_HK : OUT STD_LOGIC;
88 HK_SEL : OUT STD_LOGIC_VECTOR(1 DOWNTO 0)
89 );
90
91 END LFR_EQM;
92
93
94 SIGNAL TSTAMP : INTEGER := 0;
95 SIGNAL clk : STD_LOGIC := '0';
96 SIGNAL clk_24576Hz : STD_LOGIC := '0';
97 SIGNAL clk_24576Hz_r : STD_LOGIC := '0';
98 SIGNAL rstn : STD_LOGIC;
99
100 SIGNAL signal_gen : sample_vector(0 to ChanelCount-1,17 downto 0);
101 SIGNAL sample_fx_wdata : Samples(ChanelCount-1 DOWNTO 0);
102 SIGNAL signal_rec : sample_vector(0 to ChanelCount-1,15 downto 0);
103
104 SIGNAL end_of_simu : STD_LOGIC := '0';
105
106 CONSTANT half_samplig_period : time := 20345052 ps; --INTEGER( REAL(1000**4) / REAL(2.0*24576.0)) * 1 ps;
107
108 BEGIN
109
110 -----------------------------------------------------------------------------
111 -- CLOCK and RESET
112 -----------------------------------------------------------------------------
113 PROCESS
114 BEGIN -- PROCESS
115 WAIT UNTIL clk = '1';
116 rstn <= '0';
117 WAIT UNTIL clk = '1';
118 WAIT UNTIL clk = '1';
119 WAIT UNTIL clk = '1';
120 rstn <= '1';
121 WAIT UNTIL end_of_simu = '1';
122 WAIT FOR 10 ps;
123 assert false report "end of test" severity note;
124 -- Wait forever; this will finish the simulation.
125 wait;
126 END PROCESS;
127 -----------------------------------------------------------------------------
128
129
130 clk_24576Hz_gen:PROCESS
131 BEGIN
132 IF end_of_simu /= '1' THEN
133 clk_24576Hz <= NOT clk_24576Hz;
134 WAIT FOR half_samplig_period;
135 ELSE
136 WAIT FOR 10 ps;
137 assert false report "end of test" severity note;
138 WAIT;
139 END IF;
140 END PROCESS;
141
142 clk_25M_gen:PROCESS
143 BEGIN
144 IF end_of_simu /= '1' THEN
145 clk <= NOT clk;
146 TSTAMP <= TSTAMP+20;
147 WAIT FOR 20 ns;
148 ELSE
149 WAIT FOR 10 ps;
150 assert false report "end of test" severity note;
151 WAIT;
152 END IF;
153 END PROCESS;
154
155
156 -----------------------------------------------------------------------------
157 -- LPP_LFR_FILTER f1
158 -----------------------------------------------------------------------------
159
160 IIR_CEL_f0_to_f1 : IIR_CEL_CTRLR_v2
161 GENERIC MAP (
162 tech => tech,
163 Mem_use => Mem_use, -- use_RAM
164 Sample_SZ => 18,
165 Coef_SZ => f0_to_f1_COEFFICIENT_SIZE,
166 Coef_Nb => f0_to_f1_CEL_NUMBER*5,
167 Coef_sel_SZ => 5,
168 Cels_count => f0_to_f1_CEL_NUMBER,
169 ChanelsCount => ChanelCount,
170 FILENAME => ""
171 )
172 PORT MAP (
173 rstn => rstn,
174 clk => clk,
175 virg_pos => f0_to_f1_POINT_POSITION,
176 coefs => coefs_iir_cel_f0_to_f1,
177
178 sample_in_val => sample_val,
179 sample_in => sample,
180 sample_out_val => sample_fx_val,
181 sample_out => sample_fx);
182
183 -----------------------------------------------------------------------------
184
185
186 -----------------------------------------------------------------------------
187 -- SAMPLE GENERATION
188 -----------------------------------------------------------------------------
189
190
191 PROCESS (clk, rstn)
192 BEGIN -- PROCESS
193 IF rstn = '0' THEN -- asynchronous reset (active low)
194 sample_val <= '0';
195 clk_24576Hz_r <= '0';
196 ELSIF clk'EVENT AND clk = '1' THEN -- rising clock edge
197 clk_24576Hz_r <= clk_24576Hz;
198 IF clk_24576Hz = '1' AND clk_24576Hz_r = '0' THEN
199 sample_val <= '1';
200 ELSE
201 sample_val <= '0';
202 END IF;
203 END IF;
204 END PROCESS;
205 -----------------------------------------------------------------------------
206
207 ChanelLoop : FOR i IN 0 TO ChanelCount-1 GENERATE
208 SampleLoop : FOR j IN 0 TO 15 GENERATE
209 sample_fx_wdata(i)(j) <= sample_fx(i,j);
210 signal_rec(i,j) <= sample_fx_wdata(i)(j);
211 sample(i,j) <= signal_gen(i,j);
212 END GENERATE;
213 sample(i,16) <= signal_gen(i,16);
214 sample(i,17) <= signal_gen(i,17);
215 END GENERATE;
216
217
218
219 -----------------------------------------------------------------------------
220 -- READ INPUT SIGNALS
221 -----------------------------------------------------------------------------
222
223 gen: sig_reader
224 GENERIC MAP(
225 FNAME => "input.txt",
226 WIDTH => ChanelCount,
227 RESOLUTION => 18,
228 GAIN => 1.0
229 )
230 PORT MAP(
231 clk => sample_val,
232 end_of_simu => end_of_simu,
233 out_signal => signal_gen
234 );
235
236
237 -----------------------------------------------------------------------------
238 -- RECORD OUTPUT SIGNALS
239 -----------------------------------------------------------------------------
240
241 rec : sig_recorder
242 GENERIC MAP(
243 FNAME => "output_fx.txt",
244 WIDTH => ChanelCount,
245 RESOLUTION => 16
246 )
247 PORT MAP(
248 clk => sample_fx_val,
249 end_of_simu => end_of_simu,
250 timestamp => TSTAMP,
251 input_signal => signal_rec
252 );
253
254 END;
@@ -9,3 +9,9 MANUFACTURER=Xilinx
9 MGCPART=XC6SLX25$(PACKAGE)
9 MGCPART=XC6SLX25$(PACKAGE)
10 MGCTECHNOLOGY=SPARTAN-6
10 MGCTECHNOLOGY=SPARTAN-6
11 MGCPACKAGE=$(PACKAGE)
11 MGCPACKAGE=$(PACKAGE)
12
13 config_USB_as_FIFO:
14 ftdi_eeprom --flash-eeprom $(VHDLIB)/boards/$(BOARD)/ft2232h_JTAG_FIFO.conf
15
16 config_USB_as_UART:
17 ftdi_eeprom --flash-eeprom $(VHDLIB)/boards/$(BOARD)/ft2232h_JTAG_UART.conf
@@ -1,7 +1,6
1 # Clocks
1 # Clocks
2 NET "CLK50" PERIOD = 20 ns | LOC = "K3";
2 NET "CLK50" PERIOD = 20 ns |LOC = "K3";
3 #NET "CLK32" PERIOD = 31.25 ns | LOC = "J4";
3 #NET "CLK32" PERIOD = 31.25 ns | LOC = "J4";
4
5 # LEDs
4 # LEDs
6 NET "LEDS<0>" LOC="P11" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
5 NET "LEDS<0>" LOC="P11" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
7 NET "LEDS<1>" LOC="N9" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW;
6 NET "LEDS<1>" LOC="N9" |IOSTANDARD=LVTTL |DRIVE=8 |SLEW=SLOW;
@@ -61,4 +60,74 NET "dram_dq<12>" LOC="B16" | IOSTAN
61 NET "dram_dq<13>" LOC="B15" | IOSTANDARD=LVTTL;
60 NET "dram_dq<13>" LOC="B15" |IOSTANDARD=LVTTL;
62 NET "dram_dq<14>" LOC="C16" | IOSTANDARD=LVTTL;
61 NET "dram_dq<14>" LOC="C16" |IOSTANDARD=LVTTL;
63 NET "dram_dq<15>" LOC="C15" | IOSTANDARD=LVTTL;
62 NET "dram_dq<15>" LOC="C15" |IOSTANDARD=LVTTL;
64
63 #Created by Constraints Editor (xc6slx25-ftg256-3) - 2016/12/08
64 INST "dram_addr(0)" TNM = dram_addr;
65 INST "dram_addr(1)" TNM = dram_addr;
66 INST "dram_addr(2)" TNM = dram_addr;
67 INST "dram_addr(3)" TNM = dram_addr;
68 INST "dram_addr(4)" TNM = dram_addr;
69 INST "dram_addr(5)" TNM = dram_addr;
70 INST "dram_addr(6)" TNM = dram_addr;
71 INST "dram_addr(7)" TNM = dram_addr;
72 INST "dram_addr(8)" TNM = dram_addr;
73 INST "dram_addr(9)" TNM = dram_addr;
74 INST "dram_addr(10)" TNM = dram_addr;
75 INST "dram_addr(11)" TNM = dram_addr;
76 INST "dram_addr(12)" TNM = dram_addr;
77 INST "dram_addr(0)" TNM = dram_out;
78 INST "dram_addr(1)" TNM = dram_out;
79 INST "dram_addr(2)" TNM = dram_out;
80 INST "dram_addr(3)" TNM = dram_out;
81 INST "dram_addr(4)" TNM = dram_out;
82 INST "dram_addr(5)" TNM = dram_out;
83 INST "dram_addr(6)" TNM = dram_out;
84 INST "dram_addr(7)" TNM = dram_out;
85 INST "dram_addr(8)" TNM = dram_out;
86 INST "dram_addr(9)" TNM = dram_out;
87 INST "dram_addr(10)" TNM = dram_out;
88 INST "dram_addr(11)" TNM = dram_out;
89 INST "dram_addr(12)" TNM = dram_out;
90 INST "dram_ba_0" TNM = dram_out;
91 INST "dram_ba_1" TNM = dram_out;
92 INST "dram_cas_n" TNM = dram_out;
93 INST "dram_cke" TNM = dram_out;
94 #INST "dram_clk" TNM = dram_out;
95 INST "dram_cs_n" TNM = dram_out;
96 INST "dram_dq(0)" TNM = dram_out;
97 INST "dram_dq(1)" TNM = dram_out;
98 INST "dram_dq(2)" TNM = dram_out;
99 INST "dram_dq(3)" TNM = dram_out;
100 INST "dram_dq(4)" TNM = dram_out;
101 INST "dram_dq(5)" TNM = dram_out;
102 INST "dram_dq(6)" TNM = dram_out;
103 INST "dram_dq(7)" TNM = dram_out;
104 INST "dram_dq(8)" TNM = dram_out;
105 INST "dram_dq(9)" TNM = dram_out;
106 INST "dram_dq(10)" TNM = dram_out;
107 INST "dram_dq(11)" TNM = dram_out;
108 INST "dram_dq(12)" TNM = dram_out;
109 INST "dram_dq(13)" TNM = dram_out;
110 INST "dram_dq(14)" TNM = dram_out;
111 INST "dram_dq(15)" TNM = dram_out;
112 INST "dram_ldqm" TNM = dram_out;
113 INST "dram_ras_n" TNM = dram_out;
114 INST "dram_udqm" TNM = dram_out;
115 INST "dram_we_n" TNM = dram_out;
116 TIMEGRP "dram_out" OFFSET = OUT 12 ns AFTER "CLK50";
117 INST "dram_dq(0)" TNM = dram_in;
118 INST "dram_dq(1)" TNM = dram_in;
119 INST "dram_dq(2)" TNM = dram_in;
120 INST "dram_dq(3)" TNM = dram_in;
121 INST "dram_dq(4)" TNM = dram_in;
122 INST "dram_dq(5)" TNM = dram_in;
123 INST "dram_dq(6)" TNM = dram_in;
124 INST "dram_dq(7)" TNM = dram_in;
125 INST "dram_dq(8)" TNM = dram_in;
126 INST "dram_dq(9)" TNM = dram_in;
127 INST "dram_dq(10)" TNM = dram_in;
128 INST "dram_dq(11)" TNM = dram_in;
129 INST "dram_dq(12)" TNM = dram_in;
130 INST "dram_dq(13)" TNM = dram_in;
131 INST "dram_dq(14)" TNM = dram_in;
132 INST "dram_dq(15)" TNM = dram_in;
133 TIMEGRP "dram_in" OFFSET = IN 3 ns BEFORE "CLK50" RISING;
@@ -47,4 +47,6 PACKAGE apb_devices_list IS
47 CONSTANT LPP_APB_ADVANCED_TRIGGER : amba_device_type := 16#A3#;
47 CONSTANT LPP_APB_ADVANCED_TRIGGER : amba_device_type := 16#A3#;
48 CONSTANT LPP_APB_ADVANCED_TRIGGER_v : amba_device_type := 16#A4#;
48 CONSTANT LPP_APB_ADVANCED_TRIGGER_v : amba_device_type := 16#A4#;
49
49
50 CONSTANT LPP_AHB_FTDI_FIFO : amba_device_type := 16#A5#;
51
50 END;
52 END;
@@ -1,4 +1,5
1 lpp_sim_pkg.vhd
1 lpp_sim_pkg.vhd
2 sig_reader.vhd
2 sig_reader.vhd
3 sig_recorder.vhd
3 sig_recorder.vhd
4 lpp_sim_pkg.vhd
4 lpp_lfr_sim_pkg.vhd
5 lpp_lfr_sim_pkg.vhd
@@ -24,6 +24,8 use ieee.std_logic_1164.all;
24 library grlib;
24 library grlib;
25 use grlib.amba.all;
25 use grlib.amba.all;
26 use std.textio.all;
26 use std.textio.all;
27 library gaisler;
28 use gaisler.libdcom.all;
27 library lpp;
29 library lpp;
28 use lpp.lpp_amba.all;
30 use lpp.lpp_amba.all;
29
31
@@ -31,6 +33,71 use lpp.lpp_amba.all;
31
33
32 package lpp_usb is
34 package lpp_usb is
33
35
36 component ahb_ftdi_fifo is
37 generic (
38 oepol : integer := 0;
39 hindex : integer := 0
40 );
41 port (
42 clk : in std_logic;
43 rstn : in std_logic;
44
45 ahbi : in ahb_mst_in_type;
46 ahbo : out ahb_mst_out_type;
47
48 FTDI_RXF : in std_logic;
49 FTDI_TXE : in std_logic;
50 FTDI_SIWUA : out std_logic;
51 FTDI_WR : out std_logic;
52 FTDI_RD : out std_logic;
53 FTDI_D_in : in std_logic_vector(7 downto 0);
54 FTDI_D_out : out std_logic_vector(7 downto 0);
55 FTDI_D_drive : out std_logic
56 );
57 end component;
58
59 component ftdi_async_fifo is
60 generic (
61 oepol : integer := 0
62 );
63 port (
64 clk : in std_logic;
65 rstn : in std_logic;
66
67 dcom_in : in dcom_uart_in_type;
68 dcom_out : out dcom_uart_out_type;
69
70 FTDI_RXF : in std_logic;
71 FTDI_TXE : in std_logic;
72 FTDI_SIWUA : out std_logic;
73 FTDI_WR : out std_logic;
74 FTDI_RD : out std_logic;
75 FTDI_D_in : in std_logic_vector(7 downto 0);
76 FTDI_D_out : out std_logic_vector(7 downto 0);
77 FTDI_D_drive : out std_logic
78 );
79 end component;
80
81 component ftdi_async_fifo_loopback is
82 generic (
83 oepol : integer := 0
84 );
85 port (
86 clk : in std_logic;
87 rstn : in std_logic;
88
89
90 FTDI_RXF : in std_logic;
91 FTDI_TXE : in std_logic;
92 FTDI_SIWUA : out std_logic;
93 FTDI_WR : out std_logic;
94 FTDI_RD : out std_logic;
95 FTDI_D_in : in std_logic_vector(7 downto 0);
96 FTDI_D_out : out std_logic_vector(7 downto 0);
97 FTDI_D_drive : out std_logic
98 );
99 end component;
100
34 component FX2_Driver is
101 component FX2_Driver is
35 port(
102 port(
36 clk : in STD_LOGIC;
103 clk : in STD_LOGIC;
@@ -120,4 +187,4 end component;
120 );
187 );
121 end component;
188 end component;
122
189
123 end package; No newline at end of file
190 end package;
@@ -39,10 +39,15 if [ -d "$GRLIBPATH" ]; then
39
39
40 echo "Patch $1/lib/libs.txt..."
40 echo "Patch $1/lib/libs.txt..."
41 if(grep -q $LPP_PATCHPATH/lib/lpp $1/lib/libs.txt); then
41 if(grep -q $LPP_PATCHPATH/lib/lpp $1/lib/libs.txt); then
42 echo "No need to Patch $1/lib/libs.txt..."
42 echo "No need to add lpp in $1/lib/libs.txt..."
43 else
43 else
44 echo $LPP_PATCHPATH/lib/lpp >>$1/lib/libs.txt
44 echo $LPP_PATCHPATH/lib/lpp >>$1/lib/libs.txt
45 fi
45 fi
46 if(grep -q $LPP_PATCHPATH/lib/opencores $1/lib/libs.txt); then
47 echo "No need to add opencores in $1/lib/libs.txt..."
48 else
49 echo $LPP_PATCHPATH/lib/opencores >>$1/lib/libs.txt
50 fi
46 echo
51 echo
47 echo
52 echo
48 echo
53 echo
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (521 lines changed) Show them Hide them
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now