Merge pull request #170 from antonblanchard/litedram

LiteDRAM integration
pull/174/head
Anton Blanchard 5 years ago committed by GitHub
commit fcec66acf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -71,7 +71,8 @@ rotator_tb.o: common.o glibc_random.o ppc_fx_insns.o insn_helpers.o rotator.o
sim_console.o:
sim_uart.o: wishbone_types.o sim_console.o
xics.o: wishbone_types.o common.o
soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o wishbone_bram_wrapper.o dmi_dtm_xilinx.o wishbone_debug_master.o xics.o
soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o wishbone_bram_wrapper.o dmi_dtm_xilinx.o wishbone_debug_master.o xics.o syscon.o
syscon.o: wishbone_types.o
wishbone_arbiter.o: wishbone_types.o
wishbone_types.o:
writeback.o: common.o crhelpers.o
@ -152,11 +153,21 @@ TAGS:

.PHONY: TAGS

clean:
_clean:
rm -f *.o work-*cf unisim-*cf $(all)
rm -f fpga/*.o fpga/work-*cf
rm -f sim-unisim/*.o sim-unisim/unisim-*cf
rm -f TAGS
rm -f scripts/mw_debug/*.o
rm -f scripts/mw_debug/mw_debug

distclean: clean
clean: _clean
make -f scripts/mw_debug/Makefile clean

distclean: _clean
rm -f *~ fpga/~
rm -rf litedram/build
rm -f litedram/extras/*~
rm -f litedram/gen-src/*~
rm -f litedram/gen-src/sdram_init/*~
make -f scripts/mw_debug/Makefile distclean

@ -159,6 +159,13 @@ begin
v_int.outstanding := r_int.outstanding - 1;
end if;

if rst = '1' then
v_int.state := IDLE;
v_int.outstanding := 0;
stall_tmp := '0';
valid_tmp := '0';
end if;

-- Handle debugger stop
stopped_out <= '0';
if stop_mark_in = '1' and v_int.outstanding = 0 then
@ -228,12 +235,6 @@ begin
cr_write_valid <= '0';
end if;

if rst = '1' then
v_int.state := IDLE;
v_int.outstanding := 0;
stall_tmp := '0';
end if;

-- update outputs
valid_out <= valid_tmp;
stall_out <= stall_tmp;

@ -10,12 +10,17 @@ entity core is
generic (
SIM : boolean := false;
DISABLE_FLATTEN : boolean := false;
EX1_BYPASS : boolean := true
EX1_BYPASS : boolean := true;
ALT_RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (others => '0')
);
port (
clk : in std_logic;
rst : in std_logic;
clk : in std_ulogic;
rst : in std_ulogic;

-- Alternate reset (0xffff0000) for use by DRAM init fw
alt_reset : in std_ulogic;

-- Wishbone interface
wishbone_insn_in : in wishbone_slave_out;
wishbone_insn_out : out wishbone_master_out;

@ -125,11 +130,13 @@ begin

fetch1_0: entity work.fetch1
generic map (
RESET_ADDRESS => (others => '0')
RESET_ADDRESS => (others => '0'),
ALT_RESET_ADDRESS => ALT_RESET_ADDRESS
)
port map (
clk => clk,
rst => core_rst,
alt_reset_in => alt_reset,
stall_in => fetch1_stall_in,
flush_in => flush,
stop_in => dbg_core_stop,

@ -14,6 +14,10 @@ architecture behave of core_tb is

-- testbench signals
constant clk_period : time := 10 ns;

-- Dummy DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
begin

soc0: entity work.soc
@ -21,13 +25,17 @@ begin
SIM => true,
MEMORY_SIZE => (384*1024),
RAM_INIT_FILE => "main_ram.bin",
RESET_LOW => false
RESET_LOW => false,
CLK_FREQ => 100000000
)
port map(
rst => rst,
system_clk => clk,
uart0_rxd => '0',
uart0_txd => open
uart0_txd => open,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
alt_reset => '0'
);

clk_process: process
@ -47,4 +55,10 @@ begin
end process;

jtag: entity work.sim_jtag;

-- Dummy DRAM
wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
wb_dram_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;

end;

@ -7,7 +7,8 @@ use work.common.all;

entity fetch1 is
generic(
RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0')
RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0');
ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (others => '0')
);
port(
clk : in std_ulogic;
@ -17,6 +18,7 @@ entity fetch1 is
stall_in : in std_ulogic;
flush_in : in std_ulogic;
stop_in : in std_ulogic;
alt_reset_in : in std_ulogic;

-- redirect from execution unit
e_in : in Execute1ToFetch1Type;
@ -60,7 +62,11 @@ begin
v_int := r_int;

if rst = '1' then
if alt_reset_in = '1' then
v.nia := ALT_RESET_ADDRESS;
else
v.nia := RESET_ADDRESS;
end if;
v_int.stop_state := RUNNING;
elsif e_in.redirect = '1' then
v.nia := e_in.redirect_nia;

@ -105,6 +105,7 @@ begin
-- Clear stash on reset
if rst = '1' then
v_int.stash_valid := '0';
v.valid := '0';
end if;

-- Update registers

@ -3,8 +3,233 @@ create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { e

set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { ext_rst }];

set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart0_txd }];
set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart0_rxd }];
set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart_main_tx }];
set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_main_rx }];

##Pmod Header JC: UART (bottom)

set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_cts_n }];
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_tx }];
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rx }];
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rts_n }];

# LEDs
set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { led0_b }];
set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { led0_g }];
set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { led0_r }];

# DRAM (generated by LiteX)
## ddram:0.a
set_property LOC R2 [get_ports ddram_a[0]]
set_property SLEW FAST [get_ports ddram_a[0]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[0]]
## ddram:0.a
set_property LOC M6 [get_ports ddram_a[1]]
set_property SLEW FAST [get_ports ddram_a[1]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[1]]
## ddram:0.a
set_property LOC N4 [get_ports ddram_a[2]]
set_property SLEW FAST [get_ports ddram_a[2]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[2]]
## ddram:0.a
set_property LOC T1 [get_ports ddram_a[3]]
set_property SLEW FAST [get_ports ddram_a[3]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[3]]
## ddram:0.a
set_property LOC N6 [get_ports ddram_a[4]]
set_property SLEW FAST [get_ports ddram_a[4]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[4]]
## ddram:0.a
set_property LOC R7 [get_ports ddram_a[5]]
set_property SLEW FAST [get_ports ddram_a[5]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[5]]
## ddram:0.a
set_property LOC V6 [get_ports ddram_a[6]]
set_property SLEW FAST [get_ports ddram_a[6]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[6]]
## ddram:0.a
set_property LOC U7 [get_ports ddram_a[7]]
set_property SLEW FAST [get_ports ddram_a[7]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[7]]
## ddram:0.a
set_property LOC R8 [get_ports ddram_a[8]]
set_property SLEW FAST [get_ports ddram_a[8]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[8]]
## ddram:0.a
set_property LOC V7 [get_ports ddram_a[9]]
set_property SLEW FAST [get_ports ddram_a[9]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[9]]
## ddram:0.a
set_property LOC R6 [get_ports ddram_a[10]]
set_property SLEW FAST [get_ports ddram_a[10]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[10]]
## ddram:0.a
set_property LOC U6 [get_ports ddram_a[11]]
set_property SLEW FAST [get_ports ddram_a[11]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[11]]
## ddram:0.a
set_property LOC T6 [get_ports ddram_a[12]]
set_property SLEW FAST [get_ports ddram_a[12]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[12]]
## ddram:0.a
set_property LOC T8 [get_ports ddram_a[13]]
set_property SLEW FAST [get_ports ddram_a[13]]
set_property IOSTANDARD SSTL135 [get_ports ddram_a[13]]
## ddram:0.ba
set_property LOC R1 [get_ports ddram_ba[0]]
set_property SLEW FAST [get_ports ddram_ba[0]]
set_property IOSTANDARD SSTL135 [get_ports ddram_ba[0]]
## ddram:0.ba
set_property LOC P4 [get_ports ddram_ba[1]]
set_property SLEW FAST [get_ports ddram_ba[1]]
set_property IOSTANDARD SSTL135 [get_ports ddram_ba[1]]
## ddram:0.ba
set_property LOC P2 [get_ports ddram_ba[2]]
set_property SLEW FAST [get_ports ddram_ba[2]]
set_property IOSTANDARD SSTL135 [get_ports ddram_ba[2]]
## ddram:0.ras_n
set_property LOC P3 [get_ports ddram_ras_n]
set_property SLEW FAST [get_ports ddram_ras_n]
set_property IOSTANDARD SSTL135 [get_ports ddram_ras_n]
## ddram:0.cas_n
set_property LOC M4 [get_ports ddram_cas_n]
set_property SLEW FAST [get_ports ddram_cas_n]
set_property IOSTANDARD SSTL135 [get_ports ddram_cas_n]
## ddram:0.we_n
set_property LOC P5 [get_ports ddram_we_n]
set_property SLEW FAST [get_ports ddram_we_n]
set_property IOSTANDARD SSTL135 [get_ports ddram_we_n]
## ddram:0.cs_n
set_property LOC U8 [get_ports ddram_cs_n]
set_property SLEW FAST [get_ports ddram_cs_n]
set_property IOSTANDARD SSTL135 [get_ports ddram_cs_n]
## ddram:0.dm
set_property LOC L1 [get_ports ddram_dm[0]]
set_property SLEW FAST [get_ports ddram_dm[0]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dm[0]]
## ddram:0.dm
set_property LOC U1 [get_ports ddram_dm[1]]
set_property SLEW FAST [get_ports ddram_dm[1]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dm[1]]
## ddram:0.dq
set_property LOC K5 [get_ports ddram_dq[0]]
set_property SLEW FAST [get_ports ddram_dq[0]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[0]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[0]]
## ddram:0.dq
set_property LOC L3 [get_ports ddram_dq[1]]
set_property SLEW FAST [get_ports ddram_dq[1]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[1]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[1]]
## ddram:0.dq
set_property LOC K3 [get_ports ddram_dq[2]]
set_property SLEW FAST [get_ports ddram_dq[2]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[2]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[2]]
## ddram:0.dq
set_property LOC L6 [get_ports ddram_dq[3]]
set_property SLEW FAST [get_ports ddram_dq[3]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[3]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[3]]
## ddram:0.dq
set_property LOC M3 [get_ports ddram_dq[4]]
set_property SLEW FAST [get_ports ddram_dq[4]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[4]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[4]]
## ddram:0.dq
set_property LOC M1 [get_ports ddram_dq[5]]
set_property SLEW FAST [get_ports ddram_dq[5]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[5]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[5]]
## ddram:0.dq
set_property LOC L4 [get_ports ddram_dq[6]]
set_property SLEW FAST [get_ports ddram_dq[6]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[6]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[6]]
## ddram:0.dq
set_property LOC M2 [get_ports ddram_dq[7]]
set_property SLEW FAST [get_ports ddram_dq[7]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[7]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[7]]
## ddram:0.dq
set_property LOC V4 [get_ports ddram_dq[8]]
set_property SLEW FAST [get_ports ddram_dq[8]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[8]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[8]]
## ddram:0.dq
set_property LOC T5 [get_ports ddram_dq[9]]
set_property SLEW FAST [get_ports ddram_dq[9]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[9]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[9]]
## ddram:0.dq
set_property LOC U4 [get_ports ddram_dq[10]]
set_property SLEW FAST [get_ports ddram_dq[10]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[10]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[10]]
## ddram:0.dq
set_property LOC V5 [get_ports ddram_dq[11]]
set_property SLEW FAST [get_ports ddram_dq[11]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[11]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[11]]
## ddram:0.dq
set_property LOC V1 [get_ports ddram_dq[12]]
set_property SLEW FAST [get_ports ddram_dq[12]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[12]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[12]]
## ddram:0.dq
set_property LOC T3 [get_ports ddram_dq[13]]
set_property SLEW FAST [get_ports ddram_dq[13]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[13]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[13]]
## ddram:0.dq
set_property LOC U3 [get_ports ddram_dq[14]]
set_property SLEW FAST [get_ports ddram_dq[14]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[14]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[14]]
## ddram:0.dq
set_property LOC R3 [get_ports ddram_dq[15]]
set_property SLEW FAST [get_ports ddram_dq[15]]
set_property IOSTANDARD SSTL135 [get_ports ddram_dq[15]]
set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[15]]
## ddram:0.dqs_p
set_property LOC N2 [get_ports ddram_dqs_p[0]]
set_property SLEW FAST [get_ports ddram_dqs_p[0]]
set_property IOSTANDARD DIFF_SSTL135 [get_ports ddram_dqs_p[0]]
## ddram:0.dqs_p
set_property LOC U2 [get_ports ddram_dqs_p[1]]
set_property SLEW FAST [get_ports ddram_dqs_p[1]]
set_property IOSTANDARD DIFF_SSTL135 [get_ports ddram_dqs_p[1]]
## ddram:0.dqs_n
set_property LOC N1 [get_ports ddram_dqs_n[0]]
set_property SLEW FAST [get_ports ddram_dqs_n[0]]
set_property IOSTANDARD DIFF_SSTL135 [get_ports ddram_dqs_n[0]]
## ddram:0.dqs_n
set_property LOC V2 [get_ports ddram_dqs_n[1]]
set_property SLEW FAST [get_ports ddram_dqs_n[1]]
set_property IOSTANDARD DIFF_SSTL135 [get_ports ddram_dqs_n[1]]
## ddram:0.clk_p
set_property LOC U9 [get_ports ddram_clk_p]
set_property SLEW FAST [get_ports ddram_clk_p]
set_property IOSTANDARD DIFF_SSTL135 [get_ports ddram_clk_p]
## ddram:0.clk_n
set_property LOC V9 [get_ports ddram_clk_n]
set_property SLEW FAST [get_ports ddram_clk_n]
set_property IOSTANDARD DIFF_SSTL135 [get_ports ddram_clk_n]
## ddram:0.cke
set_property LOC N5 [get_ports ddram_cke]
set_property SLEW FAST [get_ports ddram_cke]
set_property IOSTANDARD SSTL135 [get_ports ddram_cke]
## ddram:0.odt
set_property LOC R5 [get_ports ddram_odt]
set_property SLEW FAST [get_ports ddram_odt]
set_property IOSTANDARD SSTL135 [get_ports ddram_odt]
## ddram:0.reset_n
set_property LOC K6 [get_ports ddram_reset_n]
set_property SLEW FAST [get_ports ddram_reset_n]
set_property IOSTANDARD SSTL135 [get_ports ddram_reset_n]

#Internal VREF
set_property INTERNAL_VREF 0.675 [get_iobanks 34]

set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

@ -1,23 +1,11 @@
000000004800012c
0000000000000000
4800002408000048
01006b69a600607d
a602487d05009f42
a64b5a7d14004a39
2402004ca64b7b7d
3c20000048000004
782107c660210000
60212f0064210000
618c00003d800000
658c0000798c07c6
7d8903a6618c113c
480000004e800421
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
00000000480000f4
0000000000000000
0000000000000000
0000000000000000
@ -42,6 +30,18 @@ a64b5a7d14004a39
0000000000000000
0000000000000000
0000000000000000
4800002408000048
01006b69a600607d
a602487d05009f42
a64b5a7d14004a39
2402004ca64b7b7d
3c20000048000004
782107c660210000
60211f0064210000
618c00003d800000
658c0000798c07c6
7d8903a6618c1014
480000004e800421
0000000000000000
0000000000000000
0000000000000000
@ -513,74 +513,74 @@ a64b5a7d14004a39
e8010010ebc1fff0
7c0803a6ebe1fff8
3c4000014e800020
7c0802a63842a000
3fe2fffffbe1fff8
f80100103bff7240
48000051f821ffd1
7fe3fb7860000000
60000000480001d5
7fe3fb787c641b78
600000004800017d
60000000480000ed
480001295463063e
4bffffec60000000
0100000000000000
3c40000100000180
3d20c0003842a000
6129200060000000
f922800079290020
3940001a3d20c000
7929002061292018
4e800020f9490000
612900203d20c000
7c0004ac79290020
3d40001c7d204eea
7d295392614a2000
394a0018e9428000
7c0004ac3929ffff
4e8000207d2057ea
0000000000000000
3c40000100000000
600000003842a000
390a0010e9428000
71290001e9280000
e86a00084082fff8
394000ffe9228000
7c0004ac39290020
4e8000207d404fea
0000000000000000
3c40000100000000
600000003842a000
39400000e9228000
7c0004ac39290020
4e8000207d404fea
0000000000000000
3c40000100000000
600000003842a000
39290010e9228000
7d204eea7c0004ac
4082ffe871290001
38630008e8628000
7c601eea7c0004ac
4e8000205463063e
0000000000000000
3c40000100000000
600000003842a000
390a0010e9428000
71290008e9280000
f86a00004082fff8
000000004e800020
0000000000000000
3842a0003c400001
fbc1fff07c0802a6
7fc32214fbe1fff8
f80100107c7f1b78
7fbff040f821ffd1
38210030409e000c
887f00004bffff10
4bffff993bff0001
000000004bffffe4
0000028001000000
7d4348ae39200000
409e000c2f8a0000
4e8000207d234b78
4bffffe839290001
39290010e9228000
7d204eea7c0004ac
4082ffe871290008
7c0004ace9228000
4e8000207c604fea
0000000000000000
3c40000100000000
7c0802a63842a000
3fe2fffffbe1fff8
f80100103bff7190
4bfffec1f821ffd1
4bffffad7fe3fb78
7fe3fb787c641b78
4bfffee94bffff59
4bffff195463063e
000000004bfffff4
0000018001000000
fbe1fff8fbc1fff0
7c7f1b787fc32214
f821ffd1f8010010
409e000c7fbff040
4bfffe0c38210030
3bff0001887f0000
4bffffe44bffff8d
0100000000000000
3920000000000280
2f8a00007d4348ae
7d234b78409e000c
392900014e800020
000000004bffffe8
0000000000000000
6f57206f6c6c6548
0000000a0d646c72
0000000000000010
0141780400527a01
0000001000010c1b
fffffe5800000018
0000000000000040
0000002c00000010
00000038fffffe84
0000001000000000
fffffea800000040
0000000000000034
0000005400000028
00000050fffffec8
9f029e0041094500
437e4111300e4401
4106dedf41000e0a
000000100000000b
fffffeec00000080
000000000000002c
000000940000001c
00000054ffffff04
44019f0041094400
0000007e4111300e

@ -3,8 +3,232 @@ create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_

set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports ext_rst]

set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports uart0_txd]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart0_rxd]
set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports uart_main_tx]
set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart_main_rx]

##Pmod Header JA: UART (bottom)

set_property -dict { PACKAGE_PIN Y21 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_cts_n }];
set_property -dict { PACKAGE_PIN AA21 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_tx }];
set_property -dict { PACKAGE_PIN AA20 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rx }];
set_property -dict { PACKAGE_PIN AA18 IOSTANDARD LVCMOS33 } [get_ports { uart_pmod_rts_n }];

# LEDs (no colors, just normal LEDs here)
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { led0 }];
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led1 }];

# DRAM (generated by LiteX)
## ddram:0.a
set_property LOC M2 [get_ports ddram_a[0]]
set_property SLEW FAST [get_ports ddram_a[0]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[0]]
## ddram:0.a
set_property LOC M5 [get_ports ddram_a[1]]
set_property SLEW FAST [get_ports ddram_a[1]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[1]]
## ddram:0.a
set_property LOC M3 [get_ports ddram_a[2]]
set_property SLEW FAST [get_ports ddram_a[2]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[2]]
## ddram:0.a
set_property LOC M1 [get_ports ddram_a[3]]
set_property SLEW FAST [get_ports ddram_a[3]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[3]]
## ddram:0.a
set_property LOC L6 [get_ports ddram_a[4]]
set_property SLEW FAST [get_ports ddram_a[4]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[4]]
## ddram:0.a
set_property LOC P1 [get_ports ddram_a[5]]
set_property SLEW FAST [get_ports ddram_a[5]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[5]]
## ddram:0.a
set_property LOC N3 [get_ports ddram_a[6]]
set_property SLEW FAST [get_ports ddram_a[6]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[6]]
## ddram:0.a
set_property LOC N2 [get_ports ddram_a[7]]
set_property SLEW FAST [get_ports ddram_a[7]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[7]]
## ddram:0.a
set_property LOC M6 [get_ports ddram_a[8]]
set_property SLEW FAST [get_ports ddram_a[8]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[8]]
## ddram:0.a
set_property LOC R1 [get_ports ddram_a[9]]
set_property SLEW FAST [get_ports ddram_a[9]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[9]]
## ddram:0.a
set_property LOC L5 [get_ports ddram_a[10]]
set_property SLEW FAST [get_ports ddram_a[10]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[10]]
## ddram:0.a
set_property LOC N5 [get_ports ddram_a[11]]
set_property SLEW FAST [get_ports ddram_a[11]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[11]]
## ddram:0.a
set_property LOC N4 [get_ports ddram_a[12]]
set_property SLEW FAST [get_ports ddram_a[12]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[12]]
## ddram:0.a
set_property LOC P2 [get_ports ddram_a[13]]
set_property SLEW FAST [get_ports ddram_a[13]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[13]]
## ddram:0.a
set_property LOC P6 [get_ports ddram_a[14]]
set_property SLEW FAST [get_ports ddram_a[14]]
set_property IOSTANDARD SSTL15 [get_ports ddram_a[14]]
## ddram:0.ba
set_property LOC L3 [get_ports ddram_ba[0]]
set_property SLEW FAST [get_ports ddram_ba[0]]
set_property IOSTANDARD SSTL15 [get_ports ddram_ba[0]]
## ddram:0.ba
set_property LOC K6 [get_ports ddram_ba[1]]
set_property SLEW FAST [get_ports ddram_ba[1]]
set_property IOSTANDARD SSTL15 [get_ports ddram_ba[1]]
## ddram:0.ba
set_property LOC L4 [get_ports ddram_ba[2]]
set_property SLEW FAST [get_ports ddram_ba[2]]
set_property IOSTANDARD SSTL15 [get_ports ddram_ba[2]]
## ddram:0.ras_n
set_property LOC J4 [get_ports ddram_ras_n]
set_property SLEW FAST [get_ports ddram_ras_n]
set_property IOSTANDARD SSTL15 [get_ports ddram_ras_n]
## ddram:0.cas_n
set_property LOC K3 [get_ports ddram_cas_n]
set_property SLEW FAST [get_ports ddram_cas_n]
set_property IOSTANDARD SSTL15 [get_ports ddram_cas_n]
## ddram:0.we_n
set_property LOC L1 [get_ports ddram_we_n]
set_property SLEW FAST [get_ports ddram_we_n]
set_property IOSTANDARD SSTL15 [get_ports ddram_we_n]
## ddram:0.dm
set_property LOC G3 [get_ports ddram_dm[0]]
set_property SLEW FAST [get_ports ddram_dm[0]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dm[0]]
## ddram:0.dm
set_property LOC F1 [get_ports ddram_dm[1]]
set_property SLEW FAST [get_ports ddram_dm[1]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dm[1]]
## ddram:0.dq
set_property LOC G2 [get_ports ddram_dq[0]]
set_property SLEW FAST [get_ports ddram_dq[0]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[0]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[0]]
## ddram:0.dq
set_property LOC H4 [get_ports ddram_dq[1]]
set_property SLEW FAST [get_ports ddram_dq[1]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[1]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[1]]
## ddram:0.dq
set_property LOC H5 [get_ports ddram_dq[2]]
set_property SLEW FAST [get_ports ddram_dq[2]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[2]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[2]]
## ddram:0.dq
set_property LOC J1 [get_ports ddram_dq[3]]
set_property SLEW FAST [get_ports ddram_dq[3]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[3]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[3]]
## ddram:0.dq
set_property LOC K1 [get_ports ddram_dq[4]]
set_property SLEW FAST [get_ports ddram_dq[4]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[4]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[4]]
## ddram:0.dq
set_property LOC H3 [get_ports ddram_dq[5]]
set_property SLEW FAST [get_ports ddram_dq[5]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[5]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[5]]
## ddram:0.dq
set_property LOC H2 [get_ports ddram_dq[6]]
set_property SLEW FAST [get_ports ddram_dq[6]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[6]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[6]]
## ddram:0.dq
set_property LOC J5 [get_ports ddram_dq[7]]
set_property SLEW FAST [get_ports ddram_dq[7]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[7]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[7]]
## ddram:0.dq
set_property LOC E3 [get_ports ddram_dq[8]]
set_property SLEW FAST [get_ports ddram_dq[8]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[8]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[8]]
## ddram:0.dq
set_property LOC B2 [get_ports ddram_dq[9]]
set_property SLEW FAST [get_ports ddram_dq[9]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[9]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[9]]
## ddram:0.dq
set_property LOC F3 [get_ports ddram_dq[10]]
set_property SLEW FAST [get_ports ddram_dq[10]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[10]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[10]]
## ddram:0.dq
set_property LOC D2 [get_ports ddram_dq[11]]
set_property SLEW FAST [get_ports ddram_dq[11]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[11]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[11]]
## ddram:0.dq
set_property LOC C2 [get_ports ddram_dq[12]]
set_property SLEW FAST [get_ports ddram_dq[12]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[12]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[12]]
## ddram:0.dq
set_property LOC A1 [get_ports ddram_dq[13]]
set_property SLEW FAST [get_ports ddram_dq[13]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[13]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[13]]
## ddram:0.dq
set_property LOC E2 [get_ports ddram_dq[14]]
set_property SLEW FAST [get_ports ddram_dq[14]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[14]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[14]]
## ddram:0.dq
set_property LOC B1 [get_ports ddram_dq[15]]
set_property SLEW FAST [get_ports ddram_dq[15]]
set_property IOSTANDARD SSTL15 [get_ports ddram_dq[15]]
set_property IN_TERM UNTUNED_SPLIT_50 [get_ports ddram_dq[15]]
## ddram:0.dqs_p
set_property LOC K2 [get_ports ddram_dqs_p[0]]
set_property SLEW FAST [get_ports ddram_dqs_p[0]]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[0]]
## ddram:0.dqs_p
set_property LOC E1 [get_ports ddram_dqs_p[1]]
set_property SLEW FAST [get_ports ddram_dqs_p[1]]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[1]]
## ddram:0.dqs_n
set_property LOC J2 [get_ports ddram_dqs_n[0]]
set_property SLEW FAST [get_ports ddram_dqs_n[0]]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[0]]
## ddram:0.dqs_n
set_property LOC D1 [get_ports ddram_dqs_n[1]]
set_property SLEW FAST [get_ports ddram_dqs_n[1]]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[1]]
## ddram:0.clk_p
set_property LOC P5 [get_ports ddram_clk_p]
set_property SLEW FAST [get_ports ddram_clk_p]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_p]
## ddram:0.clk_n
set_property LOC P4 [get_ports ddram_clk_n]
set_property SLEW FAST [get_ports ddram_clk_n]
set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_n]
## ddram:0.cke
set_property LOC J6 [get_ports ddram_cke]
set_property SLEW FAST [get_ports ddram_cke]
set_property IOSTANDARD SSTL15 [get_ports ddram_cke]
## ddram:0.odt
set_property LOC K4 [get_ports ddram_odt]
set_property SLEW FAST [get_ports ddram_odt]
set_property IOSTANDARD SSTL15 [get_ports ddram_odt]
## ddram:0.reset_n
set_property LOC G1 [get_ports ddram_reset_n]
set_property SLEW FAST [get_ports ddram_reset_n]
set_property IOSTANDARD SSTL15 [get_ports ddram_reset_n]

#Internal VREF
set_property INTERNAL_VREF 0.750 [get_iobanks 35]

set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

@ -0,0 +1,246 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library unisim;
use unisim.vcomponents.all;

library work;
use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : positive := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
USE_LITEDRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false
);
port(
ext_clk : in std_ulogic;
ext_rst : in std_ulogic;

-- UART0 signals:
uart_main_tx : out std_ulogic;
uart_main_rx : in std_ulogic;

-- DRAM UART signals (PMOD)
uart_pmod_tx : out std_ulogic;
uart_pmod_rx : in std_ulogic;
uart_pmod_cts_n : in std_ulogic;
uart_pmod_rts_n : out std_ulogic;

-- LEDs
led0_b : out std_ulogic;
led0_g : out std_ulogic;
led0_r : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(13 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity toplevel;

architecture behaviour of toplevel is

-- Reset signals:
signal soc_rst : std_ulogic;
signal pll_rst : std_ulogic;

-- Internal clock signals:
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- DRAM wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_csr : std_ulogic;
signal wb_dram_init : std_ulogic;

-- Control/status
signal core_alt_reset : std_ulogic;

-- Status LED
signal led0_b_pwm : std_ulogic;
signal led0_r_pwm : std_ulogic;
signal led0_g_pwm : std_ulogic;

-- Dumb PWM for the LEDs, those RGB LEDs are too bright otherwise
signal pwm_counter : std_ulogic_vector(8 downto 0);
begin

uart_pmod_rts_n <= '0';

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 256 * 1024 * 1024,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
)
port map (
system_clk => system_clk,
rst => soc_rst,
uart0_txd => uart_main_tx,
uart0_rxd => uart_main_rx,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
wb_dram_csr => wb_dram_csr,
wb_dram_init => wb_dram_init,
alt_reset => core_alt_reset
);

nodram: if not USE_LITEDRAM generate
signal ddram_clk_dummy : std_ulogic;
begin
reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst,
pll_rst_out => pll_rst,
rst_out => soc_rst
);

clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => 100000000,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map(
ext_clk => ext_clk,
pll_rst_in => pll_rst,
pll_clk_out => system_clk,
pll_locked_out => system_clk_locked
);

led0_b_pwm <= '1';
led0_r_pwm <= '1';
led0_g_pwm <= '0';
core_alt_reset <= '0';

-- Vivado barfs on those differential signals if left
-- unconnected. So instanciate a diff. buffer and feed
-- it a constant '0'.
dummy_dram_clk: OBUFDS
port map (
O => ddram_clk_p,
OB => ddram_clk_n,
I => ddram_clk_dummy
);
ddram_clk_dummy <= '0';

end generate;

has_dram: if USE_LITEDRAM generate
signal dram_init_done : std_ulogic;
signal dram_init_error : std_ulogic;
signal soc_rst_0 : std_ulogic;
signal soc_rst_1 : std_ulogic;
begin

-- Eventually dig out the frequency from the generator
-- but for now, assert it's 100Mhz
assert CLK_FREQUENCY = 100000000;

reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst,
pll_rst_out => pll_rst,
rst_out => soc_rst_0
);

dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 24,
DRAM_ALINES => 14
)
port map(
clk_in => ext_clk,
rst => pll_rst,
system_clk => system_clk,
system_reset => soc_rst_1,
core_alt_reset => core_alt_reset,
pll_locked => system_clk_locked,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_is_csr => wb_dram_csr,
wb_is_init => wb_dram_init,

serial_tx => uart_pmod_tx,
serial_rx => uart_pmod_rx,

init_done => dram_init_done,
init_error => dram_init_error,

ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n
);

led0_b_pwm <= not dram_init_done;
led0_r_pwm <= dram_init_error;
led0_g_pwm <= dram_init_done and not dram_init_error;
soc_rst <= soc_rst_0 or soc_rst_1;

end generate;

leds_pwm : process(system_clk)
begin
if rising_edge(system_clk) then
pwm_counter <= std_ulogic_vector(signed(pwm_counter) + 1);
if pwm_counter(8 downto 4) = "00000" then
led0_b <= led0_b_pwm;
led0_r <= led0_r_pwm;
led0_g <= led0_g_pwm;
else
led0_b <= '0';
led0_r <= '0';
led0_g <= '0';
end if;
end if;
end process;

end architecture behaviour;

@ -30,6 +30,10 @@ architecture behaviour of toplevel is
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- Dummy DRAM
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;

begin

reset_controller: entity work.soc_reset
@ -73,4 +77,9 @@ begin
uart0_rxd => uart0_rxd
);

-- Dummy DRAM
wb_dram_out.ack <= wb_dram_in.cyc and wb_dram_in.stb;
wb_dram_out.dat <= x"FFFFFFFFFFFFFFFF";
wb_dram_out.stall <= wb_dram_in.cyc and not wb_dram_out.ack;

end architecture behaviour;

@ -0,0 +1,209 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library unisim;
use unisim.vcomponents.all;

library work;
use work.wishbone_types.all;

entity toplevel is
generic (
MEMORY_SIZE : positive := 16384;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_FREQUENCY : positive := 100000000;
USE_LITEDRAM : boolean := false;
DISABLE_FLATTEN_CORE : boolean := false
);
port(
ext_clk : in std_ulogic;
ext_rst : in std_ulogic;

-- UART0 signals:
uart_main_tx : out std_ulogic;
uart_main_rx : in std_ulogic;

-- LEDs
led0 : out std_logic;
led1 : out std_logic;

-- DRAM wires
ddram_a : out std_logic_vector(14 downto 0);
ddram_ba : out std_logic_vector(2 downto 0);
ddram_ras_n : out std_logic;
ddram_cas_n : out std_logic;
ddram_we_n : out std_logic;
ddram_dm : out std_logic_vector(1 downto 0);
ddram_dq : inout std_logic_vector(15 downto 0);
ddram_dqs_p : inout std_logic_vector(1 downto 0);
ddram_dqs_n : inout std_logic_vector(1 downto 0);
ddram_clk_p : out std_logic;
ddram_clk_n : out std_logic;
ddram_cke : out std_logic;
ddram_odt : out std_logic;
ddram_reset_n : out std_logic
);
end entity toplevel;

architecture behaviour of toplevel is

-- Reset signals:
signal soc_rst : std_ulogic;
signal pll_rst : std_ulogic;

-- Internal clock signals:
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

-- DRAM wishbone connection
signal wb_dram_in : wishbone_master_out;
signal wb_dram_out : wishbone_slave_out;
signal wb_dram_csr : std_ulogic;
signal wb_dram_init : std_ulogic;

-- Control/status
signal core_alt_reset : std_ulogic;

begin

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
CLK_FREQ => CLK_FREQUENCY,
HAS_DRAM => USE_LITEDRAM,
DRAM_SIZE => 512 * 1024 * 1024,
DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE
)
port map (
system_clk => system_clk,
rst => soc_rst,
uart0_txd => uart_main_tx,
uart0_rxd => uart_main_rx,
wb_dram_in => wb_dram_in,
wb_dram_out => wb_dram_out,
wb_dram_csr => wb_dram_csr,
wb_dram_init => wb_dram_init,
alt_reset => core_alt_reset
);

nodram: if not USE_LITEDRAM generate
signal ddram_clk_dummy : std_ulogic;
begin
reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst,
pll_rst_out => pll_rst,
rst_out => soc_rst
);

clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => 100000000,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map(
ext_clk => ext_clk,
pll_rst_in => pll_rst,
pll_clk_out => system_clk,
pll_locked_out => system_clk_locked
);

led0 <= '1';
led1 <= not soc_rst;
core_alt_reset <= '0';

-- Vivado barfs on those differential signals if left
-- unconnected. So instanciate a diff. buffer and feed
-- it a constant '0'.
dummy_dram_clk: OBUFDS
port map (
O => ddram_clk_p,
OB => ddram_clk_n,
I => ddram_clk_dummy
);
ddram_clk_dummy <= '0';

end generate;

has_dram: if USE_LITEDRAM generate
signal dram_init_done : std_ulogic;
signal dram_init_error : std_ulogic;
signal soc_rst_0 : std_ulogic;
signal soc_rst_1 : std_ulogic;
begin

-- Eventually dig out the frequency from the generator
-- but for now, assert it's 100Mhz
assert CLK_FREQUENCY = 100000000;

reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst,
pll_rst_out => pll_rst,
rst_out => soc_rst_0
);

dram: entity work.litedram_wrapper
generic map(
DRAM_ABITS => 25,
DRAM_ALINES => 15
)
port map(
clk_in => ext_clk,
rst => pll_rst,
system_clk => system_clk,
system_reset => soc_rst_1,
pll_locked => system_clk_locked,

wb_in => wb_dram_in,
wb_out => wb_dram_out,
wb_is_csr => wb_dram_csr,
wb_is_init => wb_dram_init,

serial_tx => open,
serial_rx => '0',

init_done => dram_init_done,
init_error => dram_init_error,

ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => open,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n
);

led0 <= dram_init_done and not dram_init_error;
led1 <= dram_init_error; -- Make it blink ?
soc_rst <= soc_rst_0 or soc_rst_1;

end generate;
end architecture behaviour;

@ -9,7 +9,7 @@ CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy

CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections
CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I../include
ASFLAGS = $(CFLAGS)
LDFLAGS = -T powerpc.lds


@ -2,6 +2,10 @@
#include <stdbool.h>

#include "console.h"
#include "microwatt_soc.h"
#include "io.h"

#define UART_FREQ 115200

/*
* Core UART functions to implement for a port
@ -9,32 +13,14 @@

static uint64_t potato_uart_base;

#define PROC_FREQ 50000000
#define UART_FREQ 115200
#define UART_BASE 0xc0002000

#define POTATO_CONSOLE_TX 0x00
#define POTATO_CONSOLE_RX 0x08
#define POTATO_CONSOLE_STATUS 0x10
#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
#define POTATO_CONSOLE_STATUS_RX_FULL 0x04
#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
#define POTATO_CONSOLE_CLOCK_DIV 0x18
#define POTATO_CONSOLE_IRQ_EN 0x20

static uint64_t potato_uart_reg_read(int offset)
{
uint64_t val;

__asm__ volatile("ldcix %0,%1,%2" : "=r" (val) : "b" (potato_uart_base), "r" (offset));

return val;
return readq(potato_uart_base + offset);
}

static void potato_uart_reg_write(int offset, uint64_t val)
{
__asm__ volatile("stdcix %0,%1,%2" : : "r" (val), "b" (potato_uart_base), "r" (offset));
writeq(val, potato_uart_base + offset);
}

static int potato_uart_rx_empty(void)
@ -86,9 +72,12 @@ static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long

void potato_uart_init(void)
{
uint64_t proc_freq;

potato_uart_base = UART_BASE;
proc_freq = readq(SYSCON_BASE + SYS_REG_CLKINFO);

potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ));
potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(proc_freq, UART_FREQ));
}

void potato_uart_irq_en(void)

Binary file not shown.

Binary file not shown.

@ -515,53 +515,72 @@ e8010010ebc1fff0
3c4000014e800020
7c0802a63842a000
3fe2fffffbe1fff8
f80100103bff71a8
f80100103bff7240
48000051f821ffd1
7fe3fb7860000000
6000000048000139
60000000480001d5
7fe3fb787c641b78
60000000480000e1
6000000048000065
480000955463063e
600000004800017d
60000000480000ed
480001295463063e
4bffffec60000000
0100000000000000
3c40000100000180
3d20c0003842a000
6129200060000000
7929002039000018
3940001af9228000
4e8000207d4947ea
f922800079290020
612900203d20c000
7c0004ac79290020
3d40001c7d204eea
7d295392614a2000
394a0018e9428000
7c0004ac3929ffff
4e8000207d2057ea
0000000000000000
3c40000100000000
600000003842a000
39000010e9228000
794707e17d4946ea
386000084082fff8
5463063e7c691eea
000000004e800020
0000000000000000
3842a0003c400001
e942800060000000
7d2a46ea39000010
4082fff87927efe3
7c6a4fea39200000
000000004e800020
0000000000000000
3842a0003c400001
fbc1fff07c0802a6
3884fffffbe1fff8
7fe322143bc3ffff
f821ffd1f8010010
419e00107fbef840
4bffff9d8c7e0001
382100304bfffff0
000000004bfffe98
0000028001000000
7d4348ae39200000
419e000c2f8a0000
4bfffff039290001
4e8000207d234b78
394000ffe9228000
7c0004ac39290020
4e8000207d404fea
0000000000000000
3c40000100000000
600000003842a000
39400000e9228000
7c0004ac39290020
4e8000207d404fea
0000000000000000
3c40000100000000
600000003842a000
39290010e9228000
7d204eea7c0004ac
4082ffe871290001
38630008e8628000
7c601eea7c0004ac
4e8000205463063e
0000000000000000
3c40000100000000
600000003842a000
39290010e9228000
7d204eea7c0004ac
4082ffe871290008
7c0004ace9228000
4e8000207c604fea
0000000000000000
3c40000100000000
7c0802a63842a000
fbe1fff8fbc1fff0
7c7f1b787fc32214
f821ffd1f8010010
409e000c7fbff040
4bfffe0c38210030
3bff0001887f0000
4bffffe44bffff8d
0100000000000000
3920000000000280
2f8a00007d4348ae
7d234b78409e000c
392900014e800020
000000004bffffe8
0000000000000000
6f57206f6c6c6548
0000000a0d646c72

@ -385,7 +385,7 @@ begin
end loop;

-- Generate the "hit" and "miss" signals for the synchronous blocks
req_is_hit <= i_in.req and is_hit and not flush_in;
req_is_hit <= i_in.req and is_hit and not flush_in and not rst;
req_is_miss <= i_in.req and not is_hit and not flush_in;
req_hit_way <= hit_way;


@ -0,0 +1,53 @@
#ifndef __IO_H
#define __IO_H

static inline uint8_t readb(unsigned long addr)
{
uint8_t val;
__asm__ volatile("sync; lbzcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
return val;
}

static inline uint16_t readw(unsigned long addr)
{
uint16_t val;
__asm__ volatile("sync; lhzcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
return val;
}

static inline uint32_t readl(unsigned long addr)
{
uint32_t val;
__asm__ volatile("sync; lwzcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
return val;
}

static inline uint64_t readq(unsigned long addr)
{
uint64_t val;
__asm__ volatile("sync; ldcix %0,0,%1" : "=r" (val) : "r" (addr) : "memory");
return val;
}

static inline void writeb(uint8_t val, unsigned long addr)
{
__asm__ volatile("sync; stbcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
}

static inline void writew(uint16_t val, unsigned long addr)
{
__asm__ volatile("sync; sthcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
}

static inline void writel(uint32_t val, unsigned long addr)
{
__asm__ volatile("sync; stwcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
}

static inline void writeq(uint64_t val, unsigned long addr)
{
__asm__ volatile("sync; stdcix %0,0,%1" : : "r" (val), "r" (addr) : "memory");
}

#endif /* __IO_H */

@ -0,0 +1,34 @@
#ifndef __MICROWATT_SOC_H
#define __MICROWATT_SOC_H

/*
* Definitions for the syscon registers
*/
#define SYSCON_BASE 0xc0000000

#define SYS_REG_SIGNATURE 0x00
#define SYS_REG_INFO 0x08
#define SYS_REG_INFO_HAS_UART (1ull << 0)
#define SYS_REG_INFO_HAS_DRAM (1ull << 1)
#define SYS_REG_BRAMINFO 0x10
#define SYS_REG_DRAMINFO 0x18
#define SYS_REG_CLKINFO 0x20
#define SYS_REG_CTRL 0x28
#define SYS_REG_CTRL_DRAM_AT_0 (1ull << 0)
#define SYS_REG_CTRL_CORE_RESET (1ull << 1)
#define SYS_REG_CTRL_SOC_RESET (1ull << 2)

/* Definition for the "Potato" UART */
#define UART_BASE 0xc0002000

#define POTATO_CONSOLE_TX 0x00
#define POTATO_CONSOLE_RX 0x08
#define POTATO_CONSOLE_STATUS 0x10
#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
#define POTATO_CONSOLE_STATUS_RX_FULL 0x04
#define POTATO_CONSOLE_STATUS_TX_FULL 0x08
#define POTATO_CONSOLE_CLOCK_DIV 0x18
#define POTATO_CONSOLE_IRQ_EN 0x20

#endif /* __MICROWATT_SOC_H */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,45 @@
#!/usr/bin/python3
from fusesoc.capi2.generator import Generator
import os
import sys
import pathlib

class LiteDRAMGenerator(Generator):
def run(self):
board = self.config.get('board')

# Collect a bunch of directory path
script_dir = os.path.dirname(sys.argv[0])
base_dir = os.path.join(script_dir, os.pardir)
gen_dir = os.path.join(base_dir, "generated", board)
extras_dir = os.path.join(base_dir, "extras")

print("Adding LiteDRAM for board... ", board)

# Grab init-cpu.txt if it exists
cpu_file = os.path.join(gen_dir, "init-cpu.txt")
if os.path.exists(cpu_file):
cpu = pathlib.Path(cpu_file).read_text()
else:
cpu = None

# Add files to fusesoc
files = []
f = os.path.join(gen_dir, "litedram_core.v")
files.append({f : {'file_type' : 'verilogSource'}})
f = os.path.join(gen_dir, "litedram-wrapper.vhdl")
files.append({f : {'file_type' : 'vhdlSource-2008'}})
f = os.path.join(gen_dir, "litedram_core.init")
files.append({f : {'file_type' : 'user'}})

# Look for init CPU types and add corresponding files
if cpu == "vexriscv":
f = os.path.join(base_dir, "extras", "VexRiscv.v")
files.append({f : {'file_type' : 'verilogSource'}})

self.add_files(files)

g = LiteDRAMGenerator()
g.run()
g.write()

@ -0,0 +1,43 @@
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

{
# General ------------------------------------------------------------------
"cpu": "vexriscv", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"minimal",
"speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type

# PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K128M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "A7DDRPHY", # Type of FPGA PHY

# Electrical ---------------------------------------------------------------
"rtt_nom": "60ohm", # Nominal termination
"rtt_wr": "60ohm", # Write termination
"ron": "34ohm", # Output driver impedance

# Frequency ----------------------------------------------------------------
"input_clk_freq": 100e6, # Input clock frequency
"sys_clk_freq": 100e6, # System clock frequency (DDR_clk = 4 x sys_clk)
"iodelay_clk_freq": 200e6, # IODELAYs reference clock frequency

# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer

# User Ports ---------------------------------------------------------------
"user_ports": {
"native_0": {
"type": "native",
},
},

# CSR Port -----------------------------------------------------------------
"csr_expose": "False", # expose access to CSR (I/O) ports
"csr_align" : 32, # CSR alignment
"csr_base" : 0xc0100000 # For cpu=None only
}

@ -0,0 +1,157 @@
#!/usr/bin/python3

from fusesoc.capi2.generator import Generator
from litex.build.tools import write_to_file
from litex.build.tools import replace_in_file
from litex.build.generic_platform import *
from litex.build.xilinx import XilinxPlatform
from litex.build.lattice import LatticePlatform
from litex.soc.integration.builder import *
from litedram.gen import *
import subprocess
import os
import sys
import yaml
import shutil

def make_new_dir(base, added):
r = os.path.join(base, added)
if os.path.exists(r):
shutil.rmtree(r)
os.mkdir(r)
return r
gen_src_dir = os.path.dirname(os.path.realpath(__file__))
base_dir = os.path.join(gen_src_dir, os.pardir)
build_top_dir = make_new_dir(base_dir, "build")
gen_src_dir = os.path.join(base_dir, "gen-src")
gen_dir = make_new_dir(base_dir, "generated")

# Build the init code for microwatt-initialized DRAM
#
# XXX Not working yet
#
def build_init_code(build_dir):

# More path fudging
sw_dir = os.path.join(build_dir, "software");
sw_inc_dir = os.path.join(sw_dir, "include")
gen_inc_dir = os.path.join(sw_inc_dir, "generated")
src_dir = os.path.join(gen_src_dir, "sdram_init")
lxbios_src_dir = os.path.join(soc_directory, "software", "bios")
lxbios_inc_dir = os.path.join(soc_directory, "software", "include")
print(" sw dir:", sw_dir)
print("gen_inc_dir:", gen_inc_dir)
print(" src dir:", src_dir)
print(" lx src dir:", lxbios_src_dir)
print(" lx inc dir:", lxbios_inc_dir)

# Generate mem.h
mem_h = "#define MAIN_RAM_BASE 0x40000000"
write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h)

# Environment
env_vars = []
def _makefile_escape(s): # From LiteX
return s.replace("\\", "\\\\")
def add_var(k, v):
env_vars.append("{}={}\n".format(k, _makefile_escape(v)))

add_var("BUILD_DIR", sw_dir)
add_var("SRC_DIR", src_dir)
add_var("GENINC_DIR", sw_inc_dir)
add_var("LXSRC_DIR", lxbios_src_dir)
add_var("LXINC_DIR", lxbios_inc_dir)
write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars))

# Build init code
print(" Generating init software...")
makefile = os.path.join(src_dir, "Makefile")
r = subprocess.check_call(["make", "-C", build_dir, "-I", gen_inc_dir, "-f", makefile])
print("Make result:", r)

return os.path.join(sw_dir, "obj", "sdram_init.hex")

def generate_one(t, mw_init):

print("Generating target:", t)

# Muck with directory path
build_dir = make_new_dir(build_top_dir, t)
t_dir = make_new_dir(gen_dir, t)

# Grab config file
cfile = os.path.join(gen_src_dir, t + ".yml")
core_config = yaml.load(open(cfile).read(), Loader=yaml.Loader)

### TODO: Make most stuff below a function in litedram gen.py and
### call it rather than duplicate it
###

# Convert YAML elements to Python/LiteX
for k, v in core_config.items():
replaces = {"False": False, "True": True, "None": None}
for r in replaces.keys():
if v == r:
core_config[k] = replaces[r]
if "clk_freq" in k:
core_config[k] = float(core_config[k])
if k == "sdram_module":
core_config[k] = getattr(litedram_modules, core_config[k])
if k == "sdram_phy":
core_config[k] = getattr(litedram_phys, core_config[k])

# Override values for mw_init
if mw_init:
core_config["cpu"] = None
core_config["csr_expose"] = True
core_config["csr_align"] = 64

# Generate core
if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis")
elif core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
platform = XilinxPlatform("", io=[], toolchain="vivado")
else:
raise ValueError("Unsupported SDRAM PHY: {}".format(core_config["sdram_phy"]))

soc = LiteDRAMCore(platform, core_config, integrated_rom_size=0x6000, csr_data_width=32)

# Build into build_dir
builder = Builder(soc, output_dir=build_dir, compile_gateware=False)
vns = builder.build(build_name="litedram_core", regular_comb=False)

# Grab generated gatewar dir
gw_dir = os.path.join(build_dir, "gateware")

# Generate init-cpu.txt if any and generate init code if none
cpu = core_config["cpu"]
if mw_init:
src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl")
src_init_file = build_init_code(build_dir)
else:
write_to_file(os.path.join(t_dir, "init-cpu.txt"), cpu)
src_wrap_file = os.path.join(gen_src_dir, "wrapper-self-init.vhdl")
src_init_file = os.path.join(gw_dir, "mem.init")

# Copy generated files to target dir, amend them if necessary
core_file = os.path.join(gw_dir, "litedram_core.v")
dst_init_file = os.path.join(t_dir, "litedram_core.init")
dst_wrap_file = os.path.join(t_dir, "litedram-wrapper.vhdl")
replace_in_file(core_file, "mem.init", "litedram_core.init")
shutil.copy(core_file, t_dir)
shutil.copyfile(src_init_file, dst_init_file)
shutil.copyfile(src_wrap_file, dst_wrap_file)

def main():

targets = ['arty','nexys-video']

# XXX Set mw_init to False to use a local VexRiscV for memory inits
for t in targets:
generate_one(t, mw_init = True)

# XXX TODO: Remove build dir unless told not to via cmdline option
if __name__ == "__main__":
main()

@ -0,0 +1,42 @@
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

{
# General ------------------------------------------------------------------
"cpu": "vexriscv", # Type of CPU used for init/calib (vexriscv, lm32)
"cpu_variant":"minimal",
"speedgrade": -1, # FPGA speedgrade
"memtype": "DDR3", # DRAM type

# PHY ----------------------------------------------------------------------
"cmd_delay": 0, # Command additional delay (in taps)
"cmd_latency": 0, # Command additional latency
"sdram_module": "MT41K256M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "A7DDRPHY", # Type of FPGA PHY

# Electrical ---------------------------------------------------------------
"rtt_nom": "60ohm", # Nominal termination
"rtt_wr": "60ohm", # Write termination
"ron": "34ohm", # Output driver impedance

# Frequency ----------------------------------------------------------------
"input_clk_freq": 100e6, # Input clock frequency
"sys_clk_freq": 100e6, # System clock frequency (DDR_clk = 4 x sys_clk)
"iodelay_clk_freq": 200e6, # IODELAYs reference clock frequency

# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer

# User Ports ---------------------------------------------------------------
"user_ports": {
"native_0": {
"type": "native",
},
},

# CSR Port -----------------------------------------------------------------
"csr_expose": "False", # expose access to CSR (I/O) ports
"csr_align" : 32, # 64-bit alignment
}

@ -0,0 +1,75 @@
#### Directories

include variables.mak
OBJ = $(BUILD_DIR)/obj

PROGRAM = sdram_init
OBJECTS = $(OBJ)/head.o $(OBJ)/main.o $(OBJ)/sdram.o

#### Compiler

ARCH = $(shell uname -m)
ifneq ("$(ARCH)", "ppc64")
ifneq ("$(ARCH)", "ppc64le")
CROSS_COMPILE = powerpc64le-linux-gnu-
endif
endif

CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy

#### Flags

CPPFLAGS = -nostdinc
CPPFLAGS += -I$(SRC_DIR)/libc/include -I$(LXSRC_DIR) -I$(LXINC_DIR) -I$(GENINC_DIR) -I$(SRC_DIR)/include -I$(SRC_DIR)/../../../include
CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include)
CFLAGS = -Os -g -Wall -std=c99 -m64 -mabi=elfv2 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -fno-delete-null-pointer-checks
ASFLAGS = $(CPPFLAGS) $(CFLAGS)
LDFLAGS = -static -nostdlib -Ttext-segment=0xffff0000 -T $(SRC_DIR)/$(PROGRAM).lds --gc-sections

#### Pretty print

ifeq ($(V),1)
define Q
$(2)
endef
else
define Q
@echo " [$1] $(3)"
@$(2)
endef
endif

#### Rules. This is a bit crappy, I'm sure we can do better with the
#### handling of the various path, but this will have to do
#### until I can be bothered getting my head around the finer
#### points of Makefiles

all: objdir $(OBJ)/$(PROGRAM).hex

$(OBJ)/sdram.o: $(LXSRC_DIR)/sdram.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/%.o : $(SRC_DIR)/%.S
$(call Q,AS, $(CC) $(ASFLAGS) -c $< -o $@, $@)
$(OBJ)/%.o : $(SRC_DIR)/%.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)
$(OBJ)/%.o : $(SRC_DIR)/libc/src/%.c
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@, $@)

LIBC_SRC := $(wildcard $(SRC_DIR)/libc/src/*.c)
LIBC_OBJ := $(patsubst $(SRC_DIR)/libc/src/%.c, $(OBJ)/%.o,$(LIBC_SRC))
$(OBJ)/libc.o: $(LIBC_OBJ)
$(call Q,LD, $(LD) -r -o $@ $^, $@)

$(OBJ)/$(PROGRAM).elf: $(OBJECTS) $(OBJ)/libc.o
$(call Q,LD, $(LD) $(LDFLAGS) -o $@ $^, $@)

$(OBJ)/$(PROGRAM).bin: $(OBJ)/$(PROGRAM).elf
$(call Q,OC, $(OBJCOPY) -O binary -S $^ $@, $@)

$(OBJ)/$(PROGRAM).hex: $(OBJ)/$(PROGRAM).bin
$(call Q,HX, $(SRC_DIR)/bin2hex.py $^ > $@, $@)

objdir:
@mkdir -p $(OBJ)

@ -0,0 +1,17 @@
#!/usr/bin/python3

import sys
import subprocess
import struct

with open(sys.argv[1], "rb") as f:
while True:
word = f.read(8)
if len(word) == 8:
print("%016x" % struct.unpack('Q', word));
elif len(word) == 4:
print("00000000%08x" % struct.unpack('I', word));
elif len(word) == 0:
exit(0);
else:
raise Exception("Bad length")

@ -0,0 +1,102 @@
/* Copyright 2013-2014 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#define STACK_TOP 0xffff4000

#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b 191f; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa64b5a7d; /* mthsrr0 r10 */ \
.long 0xa64b7b7d; /* mthsrr1 r11 */ \
.long 0x2402004c; /* hrfid */ \
191:


/* Load an immediate 64-bit value into a register */
#define LOAD_IMM64(r, e) \
lis r,(e)@highest; \
ori r,r,(e)@higher; \
rldicr r,r, 32, 31; \
oris r,r, (e)@h; \
ori r,r, (e)@l;

.section ".head","ax"

. = 0
.global start
start:
FIXUP_ENDIAN

/* setup stack */
LOAD_IMM64(%r1, STACK_TOP - 0x100)
LOAD_IMM64(%r12, main)
mtctr %r12,
bctrl
ba 0

/* XXX: litedram init should not take exceptions, maybe we could get
* rid of these to save space, along with a core tweak to suppress
* exceptions in case they happen (just terminate ?)
*/

#define EXCEPTION(nr) \
.= nr; \
b .

/* More exception stubs */
EXCEPTION(0x100)
EXCEPTION(0x200)
EXCEPTION(0x300)
EXCEPTION(0x380)
EXCEPTION(0x400)
EXCEPTION(0x480)
EXCEPTION(0x500)
EXCEPTION(0x600)
EXCEPTION(0x700)
EXCEPTION(0x800)
EXCEPTION(0x900)
EXCEPTION(0x980)
EXCEPTION(0xa00)
EXCEPTION(0xb00)
EXCEPTION(0xc00)
EXCEPTION(0xd00)
EXCEPTION(0xe00)
EXCEPTION(0xe20)
EXCEPTION(0xe40)
EXCEPTION(0xe60)
EXCEPTION(0xe80)
EXCEPTION(0xf00)
EXCEPTION(0xf20)
EXCEPTION(0xf40)
EXCEPTION(0xf60)
EXCEPTION(0xf80)
#if 0
EXCEPTION(0x1000)
EXCEPTION(0x1100)
EXCEPTION(0x1200)
EXCEPTION(0x1300)
EXCEPTION(0x1400)
EXCEPTION(0x1500)
EXCEPTION(0x1600)
#endif

.text

@ -0,0 +1,17 @@
static inline void flush_cpu_dcache(void) { }
static inline void flush_l2_cache(void) { }

#define CONFIG_CPU_NOP "nop"
#define CONFIG_CLOCK_FREQUENCY 100000000

static inline void timer0_en_write(int e) { }
static inline void timer0_reload_write(int r) { }
static inline void timer0_load_write(int l) { }
static inline void timer0_update_value_write(int v) { }
static inline uint64_t timer0_value_read(void)
{
uint64_t val;

__asm__ volatile ("mfdec %0" : "=r" (val));
return val;
}

@ -0,0 +1,29 @@
/******************************************************************************
* Copyright (c) 2004, 2008, 2012 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _ASSERT_H
#define _ASSERT_H

#define assert(cond) \
do { if (!(cond)) { \
assert_fail(__FILE__ \
":" stringify(__LINE__) \
":" stringify(cond)); } \
} while(0)

void __attribute__((noreturn)) assert_fail(const char *msg);

#define stringify(expr) stringify_1(expr)
/* Double-indirection required to stringify expansions */
#define stringify_1(expr) #expr

#endif

@ -0,0 +1,54 @@
/* Copyright 2013-2014 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __COMPILER_H
#define __COMPILER_H

#ifndef __ASSEMBLY__

#include <stddef.h>

/* Macros for various compiler bits and pieces */
#define __packed __attribute__((packed))
#define __align(x) __attribute__((__aligned__(x)))
#define __unused __attribute__((unused))
#define __used __attribute__((used))
#define __section(x) __attribute__((__section__(x)))
#define __noreturn __attribute__((noreturn))
/* not __const as this has a different meaning (const) */
#define __attrconst __attribute__((const))
#define __warn_unused_result __attribute__((warn_unused_result))
#define __noinline __attribute__((noinline))

#if 0 /* Provided by gcc stddef.h */
#define offsetof(type,m) __builtin_offsetof(type,m)
#endif

#define __nomcount __attribute__((no_instrument_function))

/* Compiler barrier */
static inline void barrier(void)
{
// asm volatile("" : : : "memory");
}

#endif /* __ASSEMBLY__ */

/* Stringification macro */
#define __tostr(x) #x
#define tostr(x) __tostr(x)

#endif /* __COMPILER_H */

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _CTYPE_H
#define _CTYPE_H

#include <compiler.h>

int __attrconst isdigit(int c);
int __attrconst isxdigit(int c);
int __attrconst isprint(int c);
int __attrconst isspace(int c);

int __attrconst tolower(int c);
int __attrconst toupper(int c);

#endif

@ -0,0 +1,36 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _ERRNO_H
#define _ERRNO_H

extern int errno;

/*
* Error number definitions
*/
#define EPERM 1 /* not permitted */
#define ENOENT 2 /* file or directory not found */
#define EIO 5 /* input/output error */
#define EBADF 9 /* Bad file number */
#define ENOMEM 12 /* not enough space */
#define EACCES 13 /* permission denied */
#define EFAULT 14 /* bad address */
#define EBUSY 16 /* resource busy */
#define EEXIST 17 /* file already exists */
#define ENODEV 19 /* device not found */
#define EINVAL 22 /* invalid argument */
#define EDOM 33 /* math argument out of domain of func */
#define ERANGE 34 /* math result not representable */
#define ENOSYS 38 /* Function not implemented */

#endif

@ -0,0 +1,32 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _LIMITS_H
#define _LIMITS_H

#define UCHAR_MAX 255
#define SCHAR_MAX 127
#define SCHAR_MIN (-128)

#define USHRT_MAX 65535
#define SHRT_MAX 32767
#define SHRT_MIN (-32768)

#define UINT_MAX (4294967295U)
#define INT_MAX 2147483647
#define INT_MIN (-2147483648)

#define ULONG_MAX ((unsigned long)-1L)
#define LONG_MAX (ULONG_MAX/2)
#define LONG_MIN ((-LONG_MAX)-1)

#endif

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STDINT_H
#define _STDINT_H

typedef unsigned char uint8_t;
typedef signed char int8_t;

typedef unsigned short uint16_t;
typedef signed short int16_t;

typedef unsigned int uint32_t;
typedef signed int int32_t;

typedef unsigned long long uint64_t;
typedef signed long long int64_t;

typedef unsigned long int uintptr_t;

#endif

@ -0,0 +1,35 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STDIO_H
#define _STDIO_H

#include <stdarg.h>
#include "stddef.h"

#define EOF (-1)

int _printf(const char *format, ...) __attribute__((format (printf, 1, 2)));

#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

#define printf(f, ...) do { _printf(pr_fmt(f), ##__VA_ARGS__); } while(0)

int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format (printf, 3, 4)));
int vsnprintf(char *str, size_t size, const char *format, va_list);

int putchar(int ch);
int puts(const char *str);

#endif

@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STDLIB_H
#define _STDLIB_H

#include "stddef.h"

#define RAND_MAX 32767

int atoi(const char *str);
long atol(const char *str);
unsigned long int strtoul(const char *nptr, char **endptr, int base);
long int strtol(const char *nptr, char **endptr, int base);

#endif

@ -0,0 +1,45 @@
/******************************************************************************
* Copyright (c) 2004, 2016 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _STRING_H
#define _STRING_H

#include "stddef.h"

char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
char *strcat(char *dest, const char *src);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
int strcasecmp(const char *s1, const char *s2);
int strncasecmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
size_t strlen(const char *s);
size_t strnlen(const char *s, size_t n);
char *strstr(const char *hay, const char *needle);
char *strtok(char *src, const char *pattern);
char *strdup(const char *src);

void *memset(void *s, int c, size_t n);
void *memchr(const void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
void *memcpy_from_ci(void *destpp, const void *srcpp, size_t len);
void *memmove(void *dest, const void *src, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);

static inline int ffs(unsigned long val)
{
return __builtin_ffs(val);
}

#endif

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#ifndef _UNISTD_H
#define _UNISTD_H

#include <stddef.h>

typedef long ssize_t;

extern int open(const char *name, int flags);
extern int close(int fd);
extern ssize_t read(int fd, void *buf, size_t count);
extern ssize_t write(int fd, const void *buf, size_t count);
extern ssize_t lseek(int fd, long offset, int whence);

#endif

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isdigit(int ch)
{
switch (ch) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return 1;
default:
return 0;
}
}

@ -0,0 +1,19 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isprint(int ch)
{
return (ch >= 32 && ch < 127);
}

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isspace(int ch)
{
switch (ch) {
case ' ':
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
return 1;
default:
return 0;
}
}

@ -0,0 +1,22 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst isxdigit(int ch)
{
return (
(ch >= '0' && ch <= '9') |
(ch >= 'A' && ch <= 'F') |
(ch >= 'a' && ch <= 'f') );
}

@ -0,0 +1,28 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

void *memchr(const void *ptr, int c, size_t n);
void *memchr(const void *ptr, int c, size_t n)
{
unsigned char ch = (unsigned char)c;
const unsigned char *p = ptr;

while (n-- > 0) {
if (*p == ch)
return (void *)p;
p += 1;
}

return NULL;
}

@ -0,0 +1,29 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

int memcmp(const void *ptr1, const void *ptr2, size_t n);
int memcmp(const void *ptr1, const void *ptr2, size_t n)
{
const unsigned char *p1 = ptr1;
const unsigned char *p2 = ptr2;

while (n-- > 0) {
if (*p1 != *p2)
return (*p1 - *p2);
p1 += 1;
p2 += 1;
}

return 0;
}

@ -0,0 +1,36 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>
#include <stdint.h>

void *memcpy(void *dest, const void *src, size_t n);
void *memcpy(void *dest, const void *src, size_t n)
{
void *ret = dest;

while (n >= 8) {
*(uint64_t *)dest = *(uint64_t *)src;
dest += 8;
src += 8;
n -= 8;
}

while (n > 0) {
*(uint8_t *)dest = *(uint8_t *)src;
dest += 1;
src += 1;
n -= 1;
}

return ret;
}

@ -0,0 +1,36 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n)
{
/* Do the buffers overlap in a bad way? */
if (src < dest && src + n >= dest) {
char *cdest;
const char *csrc;
int i;

/* Copy from end to start */
cdest = dest + n - 1;
csrc = src + n - 1;
for (i = 0; i < n; i++) {
*cdest-- = *csrc--;
}
return dest;
} else {
/* Normal copy is possible */
return memcpy(dest, src, n);
}
}

@ -0,0 +1,40 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#define CACHE_LINE_SIZE 128

#include <stddef.h>

void *memset(void *dest, int c, size_t size);
void *memset(void *dest, int c, size_t size)
{
unsigned char *d = (unsigned char *)dest;
unsigned long big_c = 0;

if (c) {
big_c = c;
big_c |= (big_c << 8) | big_c;
big_c |= (big_c << 16) | big_c;
big_c |= (big_c << 32) | big_c;
}
while (size >= 8 && c == 0) {
*((unsigned long *)d) = big_c;
d+=8;
size-=8;
}

while (size-- > 0) {
*d++ = (unsigned char)c;
}

return dest;
}

@ -0,0 +1,27 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <ctype.h>

int strcasecmp(const char *s1, const char *s2);
int strcasecmp(const char *s1, const char *s2)
{
while (*s1 != 0 && *s2 != 0) {
if (toupper(*s1) != toupper(*s2))
break;
++s1;
++s2;
}

return *s1 - *s2;
}

@ -0,0 +1,26 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

size_t strlen(const char *s);
char *strcpy(char *dst, const char *src);
char *strcat(char *dst, const char *src);
char *strcat(char *dst, const char *src)
{
size_t p;

p = strlen(dst);
strcpy(&dst[p], src);

return dst;
}

@ -0,0 +1,28 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strchr(const char *s, int c);
char *strchr(const char *s, int c)
{
char cb = c;

while (*s != 0) {
if (*s == cb) {
return (char *)s;
}
s += 1;
}

return NULL;
}

@ -0,0 +1,25 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

int strcmp(const char *s1, const char *s2);
int strcmp(const char *s1, const char *s2)
{
while (*s1 != 0 && *s2 != 0) {
if (*s1 != *s2)
break;
s1 += 1;
s2 += 1;
}

return *s1 - *s2;
}

@ -0,0 +1,23 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

char *strcpy(char *dst, const char *src);
char *strcpy(char *dst, const char *src)
{
char *ptr = dst;

do {
*ptr++ = *src;
} while (*src++ != 0);

return dst;
}

@ -0,0 +1,40 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

size_t strlen(const char *s);
size_t strlen(const char *s)
{
size_t len = 0;

while (*s != 0) {
len += 1;
s += 1;
}

return len;
}

size_t strnlen(const char *s, size_t n);
size_t strnlen(const char *s, size_t n)
{
size_t len = 0;

while (*s != 0 && n) {
len += 1;
s += 1;
n--;
}

return len;
}

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <ctype.h>

int strncasecmp(const char *s1, const char *s2, size_t n);
int strncasecmp(const char *s1, const char *s2, size_t n)
{
if (n < 1)
return 0;

while (*s1 != 0 && *s2 != 0 && --n > 0) {
if (toupper(*s1) != toupper(*s2))
break;
++s1;
++s2;
}

return toupper(*s1) - toupper(*s2);
}

@ -0,0 +1,30 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

int strncmp(const char *s1, const char *s2, size_t n);
int strncmp(const char *s1, const char *s2, size_t n)
{
if (n < 1)
return 0;

while (*s1 != 0 && *s2 != 0 && --n > 0) {
if (*s1 != *s2)
break;
s1 += 1;
s2 += 1;
}

return *s1 - *s2;
}

@ -0,0 +1,33 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strncpy(char *dst, const char *src, size_t n);
char *strncpy(char *dst, const char *src, size_t n)
{
char *ret = dst;

/* Copy string */
while (*src != 0 && n > 0) {
*dst++ = *src++;
n -= 1;
}

/* strncpy always clears the rest of destination string... */
while (n > 0) {
*dst++ = 0;
n -= 1;
}

return ret;
}

@ -0,0 +1,28 @@
/******************************************************************************
* Copyright (c) 2004, 2008, 2019 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strrchr(const char *s, int c);
char *strrchr(const char *s, int c)
{
char *last = NULL;
char cb = c;

while (*s != 0) {
if (*s == cb)
last = (char *)s;
s += 1;
}

return last;
}

@ -0,0 +1,39 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

size_t strlen(const char *s);
int strncmp(const char *s1, const char *s2, size_t n);
char *strstr(const char *hay, const char *needle);
char *strstr(const char *hay, const char *needle)
{
char *pos;
size_t hlen, nlen;

if (hay == NULL || needle == NULL)
return NULL;
hlen = strlen(hay);
nlen = strlen(needle);
if (nlen < 1)
return (char *)hay;

for (pos = (char *)hay; pos < hay + hlen; pos++) {
if (strncmp(pos, needle, nlen) == 0) {
return pos;
}
}

return NULL;
}

@ -0,0 +1,48 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stddef.h>

char *strtok(char *src, const char *pattern);
char *strtok(char *src, const char *pattern)
{
static char *nxtTok;
char *retVal = NULL;

if (!src) {
src = nxtTok;
if (!src)
return retVal;
}

while (*src) {
const char *pp = pattern;
while (*pp) {
if (*pp == *src) {
break;
}
pp++;
}
if (!*pp) {
if (!retVal)
retVal = src;
else if (!src[-1])
break;
} else
*src = '\0';
src++;
}

nxtTok = src;

return retVal;
}

@ -0,0 +1,113 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stdlib.h>

long int strtol(const char *S, char **PTR,int BASE)
{
long rval = 0;
short int negative = 0;
short int digit;
// *PTR is S, unless PTR is NULL, in which case i override it with my own ptr
char* ptr;
if (PTR == NULL)
{
//override
PTR = &ptr;
}
// i use PTR to advance through the string
*PTR = (char *) S;
//check if BASE is ok
if ((BASE < 0) || BASE > 36)
{
return 0;
}
// ignore white space at beginning of S
while ((**PTR == ' ')
|| (**PTR == '\t')
|| (**PTR == '\n')
|| (**PTR == '\r')
)
{
(*PTR)++;
}
// check if S starts with "-" in which case the return value is negative
if (**PTR == '-')
{
negative = 1;
(*PTR)++;
}
// if BASE is 0... determine the base from the first chars...
if (BASE == 0)
{
// if S starts with "0x", BASE = 16, else 10
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
BASE = 16;
}
else
{
BASE = 10;
}
}
if (BASE == 16)
{
// S may start with "0x"
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
(*PTR)++;
(*PTR)++;
}
}
//until end of string
while (**PTR)
{
if (((**PTR) >= '0') && ((**PTR) <= '9'))
{
//digit (0..9)
digit = **PTR - '0';
}
else if (((**PTR) >= 'a') && ((**PTR) <='z'))
{
//alphanumeric digit lowercase(a (10) .. z (35) )
digit = (**PTR - 'a') + 10;
}
else if (((**PTR) >= 'A') && ((**PTR) <='Z'))
{
//alphanumeric digit uppercase(a (10) .. z (35) )
digit = (**PTR - 'A') + 10;
}
else
{
//end of parseable number reached...
break;
}
if (digit < BASE)
{
rval = (rval * BASE) + digit;
}
else
{
//digit found, but its too big for current base
//end of parseable number reached...
break;
}
//next...
(*PTR)++;
}
if (negative)
{
return rval * -1;
}
//else
return rval;
}

@ -0,0 +1,103 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stdlib.h>

unsigned long int strtoul(const char *S, char **PTR,int BASE)
{
unsigned long rval = 0;
short int digit;
// *PTR is S, unless PTR is NULL, in which case i override it with my own ptr
char* ptr;
if (PTR == NULL)
{
//override
PTR = &ptr;
}
// i use PTR to advance through the string
*PTR = (char *) S;
//check if BASE is ok
if ((BASE < 0) || BASE > 36)
{
return 0;
}
// ignore white space at beginning of S
while ((**PTR == ' ')
|| (**PTR == '\t')
|| (**PTR == '\n')
|| (**PTR == '\r')
)
{
(*PTR)++;
}
// if BASE is 0... determine the base from the first chars...
if (BASE == 0)
{
// if S starts with "0x", BASE = 16, else 10
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
BASE = 16;
}
else
{
BASE = 10;
}
}
if (BASE == 16)
{
// S may start with "0x"
if ((**PTR == '0') && (*((*PTR)+1) == 'x'))
{
(*PTR)++;
(*PTR)++;
}
}
//until end of string
while (**PTR)
{
if (((**PTR) >= '0') && ((**PTR) <='9'))
{
//digit (0..9)
digit = **PTR - '0';
}
else if (((**PTR) >= 'a') && ((**PTR) <='z'))
{
//alphanumeric digit lowercase(a (10) .. z (35) )
digit = (**PTR - 'a') + 10;
}
else if (((**PTR) >= 'A') && ((**PTR) <='Z'))
{
//alphanumeric digit uppercase(a (10) .. z (35) )
digit = (**PTR - 'A') + 10;
}
else
{
//end of parseable number reached...
break;
}
if (digit < BASE)
{
rval = (rval * BASE) + digit;
}
else
{
//digit found, but its too big for current base
//end of parseable number reached...
break;
}
//next...
(*PTR)++;
}
//done
return rval;
}

@ -0,0 +1,19 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include <ctype.h>

int __attrconst tolower(int c)
{
return (((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a' ) : c);
}

@ -0,0 +1,21 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <compiler.h>
#include "ctype.h"

int __attrconst toupper (int cha)
{
if((cha >= 'a') && (cha <= 'z'))
return(cha - 'a' + 'A');
return(cha);
}

@ -0,0 +1,304 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/

#include <stdbool.h>
#include <compiler.h>
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include <stdarg.h>

static const unsigned long long convert[] = {
0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF,
0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
};

static int
print_str_fill(char **buffer, size_t bufsize, char *sizec,
const char *str, char c)
{
size_t i, sizei, len;
char *bstart = *buffer;

sizei = strtoul(sizec, NULL, 10);
len = strlen(str);
if (sizei > len) {
for (i = 0;
(i < (sizei - len)) && ((*buffer - bstart) < bufsize);
i++) {
**buffer = c;
*buffer += 1;
}
}
return 1;
}

static int
print_str(char **buffer, size_t bufsize, const char *str)
{
char *bstart = *buffer;
size_t i;

for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) {
**buffer = str[i];
*buffer += 1;
}
return 1;
}

static unsigned int __attrconst
print_intlen(unsigned long value, unsigned short int base)
{
int i = 0;

while (value > 0) {
if (base == 16)
value >>= 4;
else
value /= base;
i++;
}
if (i == 0)
i = 1;
return i;
}

static int
print_itoa(char **buffer, size_t bufsize, unsigned long value,
unsigned short base, bool upper)
{
const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
char c;
int i, len;

if(base <= 2 || base > 16)
return 0;

len = i = print_intlen(value, base);

/* Don't print to buffer if bufsize is not enough. */
if (len > bufsize)
return 0;

do {
c = zeichen[value % base];
if (upper)
c = toupper(c);

(*buffer)[--i] = c;
value /= base;
} while(value);

*buffer += len;

return 1;
}



static int
print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size,
unsigned short int base, char c, int optlen)
{
int i, sizei, len;
char *bstart = *buffer;

sizei = strtoul(sizec, NULL, 10);
len = print_intlen(size, base) + optlen;
if (sizei > len) {
for (i = 0;
(i < (sizei - len)) && ((*buffer - bstart) < bufsize);
i++) {
**buffer = c;
*buffer += 1;
}
}

return 0;
}


static int
print_format(char **buffer, size_t bufsize, const char *format, void *var)
{
char *start;
unsigned int i = 0, length_mod = sizeof(int);
unsigned long value = 0;
unsigned long signBit;
char *form, sizec[32];
char sign = ' ';
bool upper = false;

form = (char *) format;
start = *buffer;

form++;
if(*form == '0' || *form == '.') {
sign = '0';
form++;
}

while ((*form != '\0') && ((*buffer - start) < bufsize)) {
switch(*form) {
case 'u':
case 'd':
case 'i':
sizec[i] = '\0';
value = (unsigned long) var;
signBit = 0x1ULL << (length_mod * 8 - 1);
if ((*form != 'u') && (signBit & value)) {
**buffer = '-';
*buffer += 1;
value = (-(unsigned long)value) & convert[length_mod];
}
print_fill(buffer, bufsize - (*buffer - start),
sizec, value, 10, sign, 0);
print_itoa(buffer, bufsize - (*buffer - start),
value, 10, upper);
break;
case 'X':
upper = true;
/* fallthrough */
case 'x':
sizec[i] = '\0';
value = (unsigned long) var & convert[length_mod];
print_fill(buffer, bufsize - (*buffer - start),
sizec, value, 16, sign, 0);
print_itoa(buffer, bufsize - (*buffer - start),
value, 16, upper);
break;
case 'O':
case 'o':
sizec[i] = '\0';
value = (long int) var & convert[length_mod];
print_fill(buffer, bufsize - (*buffer - start),
sizec, value, 8, sign, 0);
print_itoa(buffer, bufsize - (*buffer - start),
value, 8, upper);
break;
case 'p':
sizec[i] = '\0';
print_fill(buffer, bufsize - (*buffer - start),
sizec, (unsigned long) var, 16, ' ', 2);
print_str(buffer, bufsize - (*buffer - start),
"0x");
print_itoa(buffer, bufsize - (*buffer - start),
(unsigned long) var, 16, upper);
break;
case 'c':
sizec[i] = '\0';
print_fill(buffer, bufsize - (*buffer - start),
sizec, 1, 10, ' ', 0);
**buffer = (unsigned long) var;
*buffer += 1;
break;
case 's':
sizec[i] = '\0';
print_str_fill(buffer,
bufsize - (*buffer - start), sizec,
(char *) var, ' ');

print_str(buffer, bufsize - (*buffer - start),
(char *) var);
break;
case 'l':
form++;
if(*form == 'l') {
length_mod = sizeof(long long int);
} else {
form--;
length_mod = sizeof(long int);
}
break;
case 'h':
form++;
if(*form == 'h') {
length_mod = sizeof(signed char);
} else {
form--;
length_mod = sizeof(short int);
}
break;
case 'z':
length_mod = sizeof(size_t);
break;
default:
if(*form >= '0' && *form <= '9')
sizec[i++] = *form;
}
form++;
}

return (long int) (*buffer - start);
}


/*
* The vsnprintf function prints a formatted strings into a buffer.
* BUG: buffer size checking does not fully work yet
*/
int
vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
{
char *ptr, *bstart;

bstart = buffer;
ptr = (char *) format;

/*
* Return from here if size passed is zero, otherwise we would
* overrun buffer while setting NULL character at the end.
*/
if (!buffer || !bufsize)
return 0;

/* Leave one space for NULL character */
bufsize--;

while(*ptr != '\0' && (buffer - bstart) < bufsize)
{
if(*ptr == '%') {
char formstr[20];
int i=0;
do {
formstr[i] = *ptr;
ptr++;
i++;
} while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X'
|| *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%'
|| *ptr == 'O' || *ptr == 'o' ));
formstr[i++] = *ptr;
formstr[i] = '\0';
if(*ptr == '%') {
*buffer++ = '%';
} else {
print_format(&buffer,
bufsize - (buffer - bstart),
formstr, va_arg(arg, void *));
}
ptr++;
} else {

*buffer = *ptr;

buffer++;
ptr++;
}
}
*buffer = '\0';

return (buffer - bstart);
}

@ -0,0 +1,156 @@
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>

#include <generated/git.h>

#include "microwatt_soc.h"
#include "io.h"
#include "sdram.h"

/*
* Core UART functions to implement for a port
*/

static uint64_t potato_uart_base;

#define PROC_FREQ 100000000
#define UART_FREQ 115200

static uint8_t potato_uart_reg_read(int offset)
{
return readb(potato_uart_base + offset);
}

static void potato_uart_reg_write(int offset, uint8_t val)
{
writeb(val, potato_uart_base + offset);
}

static bool potato_uart_rx_empty(void)
{
uint8_t val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);

return (val & POTATO_CONSOLE_STATUS_RX_EMPTY) != 0;
}

static int potato_uart_tx_full(void)
{
uint8_t val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);

return (val & POTATO_CONSOLE_STATUS_TX_FULL) != 0;
}

static char potato_uart_read(void)
{
return potato_uart_reg_read(POTATO_CONSOLE_RX);
}

static void potato_uart_write(char c)
{
potato_uart_reg_write(POTATO_CONSOLE_TX, c);
}

static unsigned long potato_uart_divisor(unsigned long proc_freq,
unsigned long uart_freq)
{
return proc_freq / (uart_freq * 16) - 1;
}

void potato_uart_init(void)
{
potato_uart_base = UART_BASE;

potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV,
potato_uart_divisor(PROC_FREQ, UART_FREQ));
}

int getchar(void)
{
while (potato_uart_rx_empty())
/* Do nothing */ ;

return potato_uart_read();
}

int putchar(int c)
{
while (potato_uart_tx_full())
/* Do Nothing */;

potato_uart_write(c);
return c;
}

void putstr(const char *str, unsigned long len)
{
for (unsigned long i = 0; i < len; i++) {
if (str[i] == '\n')
putchar('\r');
putchar(str[i]);
}
}

int _printf(const char *fmt, ...)
{
int count;
char buffer[320];
va_list ap;

va_start(ap, fmt);
count = vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
putstr(buffer, count);
return count;
}

void flush_cpu_dcache(void) { }
void flush_cpu_icache(void) { }
void flush_l2_cache(void) { }

void main(void)
{
unsigned long long ftr, val;
int i;

/*
* Let things settle ... not sure why but the UART is
* not happy otherwise. The PLL might need to settle ?
*/
potato_uart_init();
for (i = 0; i < 100000; i++)
potato_uart_reg_read(POTATO_CONSOLE_STATUS);
printf("\n\nWelcome to Microwatt !\n\n");

/* TODO: Add core version information somewhere in syscon, possibly
* extracted from git
*/
printf(" Soc signature: %016llx\n",
(unsigned long long)readq(SYSCON_BASE + SYS_REG_SIGNATURE));
printf(" Soc features: ");
ftr = readq(SYSCON_BASE + SYS_REG_INFO);
if (ftr & SYS_REG_INFO_HAS_UART)
printf("UART ");
if (ftr & SYS_REG_INFO_HAS_DRAM)
printf("DRAM ");
printf("\n");
val = readq(SYSCON_BASE + SYS_REG_BRAMINFO);
printf(" BRAM: %lld KB\n", val / 1024);
if (ftr & SYS_REG_INFO_HAS_DRAM) {
val = readq(SYSCON_BASE + SYS_REG_DRAMINFO);
printf(" DRAM: %lld MB\n", val / (1024 * 1024));
}
val = readq(SYSCON_BASE + SYS_REG_CLKINFO);
printf(" CLK: %lld MHz\n", val / 1000000);

printf("\n");
if (ftr & SYS_REG_INFO_HAS_DRAM) {
printf("LiteDRAM built from Migen %s and LiteX %s\n",
MIGEN_GIT_SHA1, LITEX_GIT_SHA1);
sdrinit();
}
printf("Booting from BRAM...\n");
}

@ -0,0 +1,12 @@
SECTIONS
{
. = 0xffff0000;
start = .;
.head : {
KEEP(*(.head))
}
. = 0xffff1000;
.text : { *(.text*) *(.sfpr) *(.rodata*) }
.data : { *(.data*) }
.bss : { *(.bss*) }
}

@ -0,0 +1,303 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive
);
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
clk_in : in std_ulogic;
rst : in std_ulogic;
system_clk : out std_ulogic;
system_reset : out std_ulogic;
core_alt_reset : out std_ulogic;
pll_locked : out std_ulogic;

-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_csr : in std_ulogic;
wb_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;

-- Misc
init_done : out std_ulogic;
init_error : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is

component litedram_core port (
clk : in std_ulogic;
rst : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
csr_port0_adr : in std_ulogic_vector(13 downto 0);
csr_port0_we : in std_ulogic;
csr_port0_dat_w : in std_ulogic_vector(31 downto 0);
csr_port0_dat_r : out std_ulogic_vector(31 downto 0);
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic;
user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port_native_0_wdata_valid : in std_ulogic;
user_port_native_0_wdata_ready : out std_ulogic;
user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port_native_0_rdata_valid : out std_ulogic;
user_port_native_0_rdata_ready : in std_ulogic;
user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0)
);
end component;
signal user_port0_cmd_valid : std_ulogic;
signal user_port0_cmd_ready : std_ulogic;
signal user_port0_cmd_we : std_ulogic;
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0);
signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0);

signal ad3 : std_ulogic;

signal dram_user_reset : std_ulogic;

signal csr_port0_adr : std_ulogic_vector(13 downto 0);
signal csr_port0_we : std_ulogic;
signal csr_port0_dat_w : std_ulogic_vector(31 downto 0);
signal csr_port0_dat_r : std_ulogic_vector(31 downto 0);
signal csr_port_read_comb : std_ulogic_vector(63 downto 0);
signal csr_valid : std_ulogic;
signal csr_write_valid : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;

type state_t is (CMD, MWRITE, MREAD, CSR);
signal state : state_t;

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i) := temp_word;
end loop;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

begin

-- BRAM Memory slave
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
for i in 0 to 7 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_init_out.ack <= not wb_init_out.ack;
end if;
end if;
end process;

wb_init_in.adr <= wb_in.adr;
wb_init_in.dat <= wb_in.dat;
wb_init_in.sel <= wb_in.sel;
wb_init_in.we <= wb_in.we;
wb_init_in.stb <= wb_in.stb;
wb_init_in.cyc <= wb_in.cyc and wb_is_init;

-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
ad3 <= wb_in.adr(3);

-- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init)
when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
user_port0_wdata_data <= wb_in.dat & wb_in.dat;
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- DRAM CSR interface signals. We only support access to the bottom byte
csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr;
csr_write_valid <= wb_in.we and wb_in.sel(0);
csr_port0_adr <= wb_in.adr(15 downto 2) when wb_is_csr = '1' else (others => '0');
csr_port0_dat_w <= wb_in.dat(31 downto 0);
csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0';

-- Wishbone out signals
wb_out.ack <= '1' when state = CSR else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';

csr_port_read_comb <= x"00000000" & csr_port0_dat_r;
wb_out.dat <= csr_port_read_comb when wb_is_csr = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

-- Reset ignored, the reset controller use the pll lock signal,
-- and alternate core reset address set when DRAM is not initialized.
--
system_reset <= '0';
core_alt_reset <= not init_done;

-- State machine
sm: process(system_clk)
begin
if rising_edge(system_clk) then
if dram_user_reset = '1' then
state <= CMD;
else
case state is
when CMD =>
if csr_valid = '1' then
state <= CSR;
elsif (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD;
end if;
when MWRITE =>
if user_port0_wdata_ready = '1' then
state <= CMD;
end if;
when MREAD =>
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
when CSR =>
state <= CMD;
end case;
end if;
end if;
end process;

litedram: litedram_core
port map(
clk => clk_in,
rst => rst,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n,
init_done => init_done,
init_error => init_error,
user_clk => system_clk,
user_rst => dram_user_reset,
csr_port0_adr => csr_port0_adr,
csr_port0_we => csr_port0_we,
csr_port0_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r,
user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port_native_0_cmd_we => user_port0_cmd_we,
user_port_native_0_cmd_addr => user_port0_cmd_addr,
user_port_native_0_wdata_valid => user_port0_wdata_valid,
user_port_native_0_wdata_ready => user_port0_wdata_ready,
user_port_native_0_wdata_we => user_port0_wdata_we,
user_port_native_0_wdata_data => user_port0_wdata_data,
user_port_native_0_rdata_valid => user_port0_rdata_valid,
user_port_native_0_rdata_ready => user_port0_rdata_ready,
user_port_native_0_rdata_data => user_port0_rdata_data
);

end architecture behaviour;

@ -0,0 +1,214 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive
);
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
clk_in : in std_ulogic;
rst : in std_ulogic;
system_clk : out std_ulogic;
system_reset : out std_ulogic;
core_alt_reset : out std_ulogic;
pll_locked : out std_ulogic;

-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_csr : in std_ulogic;
wb_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;

-- Misc
init_done : out std_ulogic;
init_error : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is

component litedram_core port (
clk : in std_ulogic;
rst : in std_ulogic;
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic;
user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port_native_0_wdata_valid : in std_ulogic;
user_port_native_0_wdata_ready : out std_ulogic;
user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port_native_0_rdata_valid : out std_ulogic;
user_port_native_0_rdata_ready : in std_ulogic;
user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0)
);
end component;
signal user_port0_cmd_valid : std_ulogic;
signal user_port0_cmd_ready : std_ulogic;
signal user_port0_cmd_we : std_ulogic;
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0);
signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0);

signal ad3 : std_ulogic;

signal dram_user_reset : std_ulogic;

type state_t is (CMD, MWRITE, MREAD);
signal state : state_t;

begin

-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
ad3 <= wb_in.adr(3);

-- DRAM interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init)
when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
user_port0_wdata_data <= wb_in.dat & wb_in.dat;
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- Wishbone out signals. CSR and init memory do nothing, just ack
wb_out.ack <= '1' when (wb_is_csr = '1' or wb_is_init = '1') else
user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';
wb_out.dat <= (others => '0') when (wb_is_csr = '1' or wb_is_init = '1') else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

-- Reset, lift it when init done, no alt core reset
system_reset <= dram_user_reset or not init_done;
core_alt_reset <= '0';

-- State machine
sm: process(system_clk)
begin
if rising_edge(system_clk) then
if dram_user_reset = '1' then
state <= CMD;
else
case state is
when CMD =>
if (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD;
end if;
when MWRITE =>
if user_port0_wdata_ready = '1' then
state <= CMD;
end if;
when MREAD =>
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
end case;
end if;
end if;
end process;

litedram: litedram_core
port map(
clk => clk_in,
rst => rst,
serial_tx => serial_tx,
serial_rx => serial_rx,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n,
init_done => init_done,
init_error => init_error,
user_clk => system_clk,
user_rst => dram_user_reset,
user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port_native_0_cmd_we => user_port0_cmd_we,
user_port_native_0_cmd_addr => user_port0_cmd_addr,
user_port_native_0_wdata_valid => user_port0_wdata_valid,
user_port_native_0_wdata_ready => user_port0_wdata_ready,
user_port_native_0_wdata_we => user_port0_wdata_we,
user_port_native_0_wdata_data => user_port0_wdata_data,
user_port_native_0_rdata_valid => user_port0_rdata_valid,
user_port_native_0_rdata_ready => user_port0_rdata_ready,
user_port_native_0_rdata_data => user_port0_rdata_data
);

end architecture behaviour;

@ -0,0 +1,303 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive
);
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
clk_in : in std_ulogic;
rst : in std_ulogic;
system_clk : out std_ulogic;
system_reset : out std_ulogic;
core_alt_reset : out std_ulogic;
pll_locked : out std_ulogic;

-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_csr : in std_ulogic;
wb_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;

-- Misc
init_done : out std_ulogic;
init_error : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is

component litedram_core port (
clk : in std_ulogic;
rst : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
csr_port0_adr : in std_ulogic_vector(13 downto 0);
csr_port0_we : in std_ulogic;
csr_port0_dat_w : in std_ulogic_vector(31 downto 0);
csr_port0_dat_r : out std_ulogic_vector(31 downto 0);
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic;
user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port_native_0_wdata_valid : in std_ulogic;
user_port_native_0_wdata_ready : out std_ulogic;
user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port_native_0_rdata_valid : out std_ulogic;
user_port_native_0_rdata_ready : in std_ulogic;
user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0)
);
end component;
signal user_port0_cmd_valid : std_ulogic;
signal user_port0_cmd_ready : std_ulogic;
signal user_port0_cmd_we : std_ulogic;
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0);
signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0);

signal ad3 : std_ulogic;

signal dram_user_reset : std_ulogic;

signal csr_port0_adr : std_ulogic_vector(13 downto 0);
signal csr_port0_we : std_ulogic;
signal csr_port0_dat_w : std_ulogic_vector(31 downto 0);
signal csr_port0_dat_r : std_ulogic_vector(31 downto 0);
signal csr_port_read_comb : std_ulogic_vector(63 downto 0);
signal csr_valid : std_ulogic;
signal csr_write_valid : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;

type state_t is (CMD, MWRITE, MREAD, CSR);
signal state : state_t;

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i) := temp_word;
end loop;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

begin

-- BRAM Memory slave
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
for i in 0 to 7 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_init_out.ack <= not wb_init_out.ack;
end if;
end if;
end process;

wb_init_in.adr <= wb_in.adr;
wb_init_in.dat <= wb_in.dat;
wb_init_in.sel <= wb_in.sel;
wb_init_in.we <= wb_in.we;
wb_init_in.stb <= wb_in.stb;
wb_init_in.cyc <= wb_in.cyc and wb_is_init;

-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
ad3 <= wb_in.adr(3);

-- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init)
when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
user_port0_wdata_data <= wb_in.dat & wb_in.dat;
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- DRAM CSR interface signals. We only support access to the bottom byte
csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr;
csr_write_valid <= wb_in.we and wb_in.sel(0);
csr_port0_adr <= wb_in.adr(15 downto 2) when wb_is_csr = '1' else (others => '0');
csr_port0_dat_w <= wb_in.dat(31 downto 0);
csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0';

-- Wishbone out signals
wb_out.ack <= '1' when state = CSR else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';

csr_port_read_comb <= x"00000000" & csr_port0_dat_r;
wb_out.dat <= csr_port_read_comb when wb_is_csr = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

-- Reset ignored, the reset controller use the pll lock signal,
-- and alternate core reset address set when DRAM is not initialized.
--
system_reset <= '0';
core_alt_reset <= not init_done;

-- State machine
sm: process(system_clk)
begin
if rising_edge(system_clk) then
if dram_user_reset = '1' then
state <= CMD;
else
case state is
when CMD =>
if csr_valid = '1' then
state <= CSR;
elsif (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD;
end if;
when MWRITE =>
if user_port0_wdata_ready = '1' then
state <= CMD;
end if;
when MREAD =>
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
when CSR =>
state <= CMD;
end case;
end if;
end if;
end process;

litedram: litedram_core
port map(
clk => clk_in,
rst => rst,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n,
init_done => init_done,
init_error => init_error,
user_clk => system_clk,
user_rst => dram_user_reset,
csr_port0_adr => csr_port0_adr,
csr_port0_we => csr_port0_we,
csr_port0_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r,
user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port_native_0_cmd_we => user_port0_cmd_we,
user_port_native_0_cmd_addr => user_port0_cmd_addr,
user_port_native_0_wdata_valid => user_port0_wdata_valid,
user_port_native_0_wdata_ready => user_port0_wdata_ready,
user_port_native_0_wdata_we => user_port0_wdata_we,
user_port_native_0_wdata_data => user_port0_wdata_data,
user_port_native_0_rdata_valid => user_port0_rdata_valid,
user_port_native_0_rdata_ready => user_port0_rdata_ready,
user_port_native_0_rdata_data => user_port0_rdata_data
);

end architecture behaviour;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,303 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

library work;
use work.wishbone_types.all;
use work.sim_console.all;

entity litedram_wrapper is
generic (
DRAM_ABITS : positive;
DRAM_ALINES : positive
);
port(
-- LiteDRAM generates the system clock and reset
-- from the input clkin
clk_in : in std_ulogic;
rst : in std_ulogic;
system_clk : out std_ulogic;
system_reset : out std_ulogic;
core_alt_reset : out std_ulogic;
pll_locked : out std_ulogic;

-- Wishbone ports:
wb_in : in wishbone_master_out;
wb_out : out wishbone_slave_out;
wb_is_csr : in std_ulogic;
wb_is_init : in std_ulogic;

-- Init core serial debug
serial_tx : out std_ulogic;
serial_rx : in std_ulogic;

-- Misc
init_done : out std_ulogic;
init_error : out std_ulogic;

-- DRAM wires
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic
);
end entity litedram_wrapper;

architecture behaviour of litedram_wrapper is

component litedram_core port (
clk : in std_ulogic;
rst : in std_ulogic;
pll_locked : out std_ulogic;
ddram_a : out std_ulogic_vector(DRAM_ALINES-1 downto 0);
ddram_ba : out std_ulogic_vector(2 downto 0);
ddram_ras_n : out std_ulogic;
ddram_cas_n : out std_ulogic;
ddram_we_n : out std_ulogic;
ddram_cs_n : out std_ulogic;
ddram_dm : out std_ulogic_vector(1 downto 0);
ddram_dq : inout std_ulogic_vector(15 downto 0);
ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
ddram_clk_p : out std_ulogic;
ddram_clk_n : out std_ulogic;
ddram_cke : out std_ulogic;
ddram_odt : out std_ulogic;
ddram_reset_n : out std_ulogic;
init_done : out std_ulogic;
init_error : out std_ulogic;
user_clk : out std_ulogic;
user_rst : out std_ulogic;
csr_port0_adr : in std_ulogic_vector(13 downto 0);
csr_port0_we : in std_ulogic;
csr_port0_dat_w : in std_ulogic_vector(31 downto 0);
csr_port0_dat_r : out std_ulogic_vector(31 downto 0);
user_port_native_0_cmd_valid : in std_ulogic;
user_port_native_0_cmd_ready : out std_ulogic;
user_port_native_0_cmd_we : in std_ulogic;
user_port_native_0_cmd_addr : in std_ulogic_vector(DRAM_ABITS-1 downto 0);
user_port_native_0_wdata_valid : in std_ulogic;
user_port_native_0_wdata_ready : out std_ulogic;
user_port_native_0_wdata_we : in std_ulogic_vector(15 downto 0);
user_port_native_0_wdata_data : in std_ulogic_vector(127 downto 0);
user_port_native_0_rdata_valid : out std_ulogic;
user_port_native_0_rdata_ready : in std_ulogic;
user_port_native_0_rdata_data : out std_ulogic_vector(127 downto 0)
);
end component;
signal user_port0_cmd_valid : std_ulogic;
signal user_port0_cmd_ready : std_ulogic;
signal user_port0_cmd_we : std_ulogic;
signal user_port0_cmd_addr : std_ulogic_vector(DRAM_ABITS-1 downto 0);
signal user_port0_wdata_valid : std_ulogic;
signal user_port0_wdata_ready : std_ulogic;
signal user_port0_wdata_we : std_ulogic_vector(15 downto 0);
signal user_port0_wdata_data : std_ulogic_vector(127 downto 0);
signal user_port0_rdata_valid : std_ulogic;
signal user_port0_rdata_ready : std_ulogic;
signal user_port0_rdata_data : std_ulogic_vector(127 downto 0);

signal ad3 : std_ulogic;

signal dram_user_reset : std_ulogic;

signal csr_port0_adr : std_ulogic_vector(13 downto 0);
signal csr_port0_we : std_ulogic;
signal csr_port0_dat_w : std_ulogic_vector(31 downto 0);
signal csr_port0_dat_r : std_ulogic_vector(31 downto 0);
signal csr_port_read_comb : std_ulogic_vector(63 downto 0);
signal csr_valid : std_ulogic;
signal csr_write_valid : std_ulogic;

signal wb_init_in : wishbone_master_out;
signal wb_init_out : wishbone_slave_out;

type state_t is (CMD, MWRITE, MREAD, CSR);
signal state : state_t;

constant INIT_RAM_SIZE : integer := 16384;
constant INIT_RAM_ABITS :integer := 14;
constant INIT_RAM_FILE : string := "litedram_core.init";

type ram_t is array(0 to (INIT_RAM_SIZE / 8) - 1) of std_logic_vector(63 downto 0);

impure function init_load_ram(name : string) return ram_t is
file ram_file : text open read_mode is name;
variable temp_word : std_logic_vector(63 downto 0);
variable temp_ram : ram_t := (others => (others => '0'));
variable ram_line : line;
begin
for i in 0 to (INIT_RAM_SIZE/8)-1 loop
exit when endfile(ram_file);
readline(ram_file, ram_line);
hread(ram_line, temp_word);
temp_ram(i) := temp_word;
end loop;
return temp_ram;
end function;

signal init_ram : ram_t := init_load_ram(INIT_RAM_FILE);

attribute ram_style : string;
attribute ram_style of init_ram: signal is "block";

begin

-- BRAM Memory slave
init_ram_0: process(system_clk)
variable adr : integer;
begin
if rising_edge(system_clk) then
wb_init_out.ack <= '0';
if (wb_init_in.cyc and wb_init_in.stb) = '1' then
adr := to_integer((unsigned(wb_init_in.adr(INIT_RAM_ABITS-1 downto 3))));
if wb_init_in.we = '0' then
wb_init_out.dat <= init_ram(adr);
else
for i in 0 to 7 loop
if wb_init_in.sel(i) = '1' then
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
wb_init_in.dat(((i + 1) * 8) - 1 downto i * 8);
end if;
end loop;
end if;
wb_init_out.ack <= not wb_init_out.ack;
end if;
end if;
end process;

wb_init_in.adr <= wb_in.adr;
wb_init_in.dat <= wb_in.dat;
wb_init_in.sel <= wb_in.sel;
wb_init_in.we <= wb_in.we;
wb_init_in.stb <= wb_in.stb;
wb_init_in.cyc <= wb_in.cyc and wb_is_init;

-- Address bit 3 selects the top or bottom half of the data
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
--
ad3 <= wb_in.adr(3);

-- DRAM data interface signals
user_port0_cmd_valid <= (wb_in.cyc and wb_in.stb and not wb_is_csr and not wb_is_init)
when state = CMD else '0';
user_port0_cmd_we <= wb_in.we when state = CMD else '0';
user_port0_wdata_valid <= '1' when state = MWRITE else '0';
user_port0_rdata_ready <= '1' when state = MREAD else '0';
user_port0_cmd_addr <= wb_in.adr(DRAM_ABITS+3 downto 4);
user_port0_wdata_data <= wb_in.dat & wb_in.dat;
user_port0_wdata_we <= wb_in.sel & "00000000" when ad3 = '1' else
"00000000" & wb_in.sel;

-- DRAM CSR interface signals. We only support access to the bottom byte
csr_valid <= wb_in.cyc and wb_in.stb and wb_is_csr;
csr_write_valid <= wb_in.we and wb_in.sel(0);
csr_port0_adr <= wb_in.adr(15 downto 2) when wb_is_csr = '1' else (others => '0');
csr_port0_dat_w <= wb_in.dat(31 downto 0);
csr_port0_we <= (csr_valid and csr_write_valid) when state = CMD else '0';

-- Wishbone out signals
wb_out.ack <= '1' when state = CSR else
wb_init_out.ack when wb_is_init = '1' else
user_port0_wdata_ready when state = MWRITE else
user_port0_rdata_valid when state = MREAD else '0';

csr_port_read_comb <= x"00000000" & csr_port0_dat_r;
wb_out.dat <= csr_port_read_comb when wb_is_csr = '1' else
wb_init_out.dat when wb_is_init = '1' else
user_port0_rdata_data(127 downto 64) when ad3 = '1' else
user_port0_rdata_data(63 downto 0);
-- We don't do pipelining yet.
wb_out.stall <= '0' when wb_in.cyc = '0' else not wb_out.ack;

-- Reset ignored, the reset controller use the pll lock signal,
-- and alternate core reset address set when DRAM is not initialized.
--
system_reset <= '0';
core_alt_reset <= not init_done;

-- State machine
sm: process(system_clk)
begin
if rising_edge(system_clk) then
if dram_user_reset = '1' then
state <= CMD;
else
case state is
when CMD =>
if csr_valid = '1' then
state <= CSR;
elsif (user_port0_cmd_ready and user_port0_cmd_valid) = '1' then
state <= MWRITE when wb_in.we = '1' else MREAD;
end if;
when MWRITE =>
if user_port0_wdata_ready = '1' then
state <= CMD;
end if;
when MREAD =>
if user_port0_rdata_valid = '1' then
state <= CMD;
end if;
when CSR =>
state <= CMD;
end case;
end if;
end if;
end process;

litedram: litedram_core
port map(
clk => clk_in,
rst => rst,
pll_locked => pll_locked,
ddram_a => ddram_a,
ddram_ba => ddram_ba,
ddram_ras_n => ddram_ras_n,
ddram_cas_n => ddram_cas_n,
ddram_we_n => ddram_we_n,
ddram_cs_n => ddram_cs_n,
ddram_dm => ddram_dm,
ddram_dq => ddram_dq,
ddram_dqs_p => ddram_dqs_p,
ddram_dqs_n => ddram_dqs_n,
ddram_clk_p => ddram_clk_p,
ddram_clk_n => ddram_clk_n,
ddram_cke => ddram_cke,
ddram_odt => ddram_odt,
ddram_reset_n => ddram_reset_n,
init_done => init_done,
init_error => init_error,
user_clk => system_clk,
user_rst => dram_user_reset,
csr_port0_adr => csr_port0_adr,
csr_port0_we => csr_port0_we,
csr_port0_dat_w => csr_port0_dat_w,
csr_port0_dat_r => csr_port0_dat_r,
user_port_native_0_cmd_valid => user_port0_cmd_valid,
user_port_native_0_cmd_ready => user_port0_cmd_ready,
user_port_native_0_cmd_we => user_port0_cmd_we,
user_port_native_0_cmd_addr => user_port0_cmd_addr,
user_port_native_0_wdata_valid => user_port0_wdata_valid,
user_port_native_0_wdata_ready => user_port0_wdata_ready,
user_port_native_0_wdata_we => user_port0_wdata_we,
user_port_native_0_wdata_data => user_port0_wdata_data,
user_port_native_0_rdata_valid => user_port0_rdata_valid,
user_port_native_0_rdata_ready => user_port0_rdata_ready,
user_port_native_0_rdata_data => user_port0_rdata_data
);

end architecture behaviour;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,15 @@
CAPI=2:

name : :microwatt:litedram:0

generators:
litedram_gen:
interpreter: python3
command: extras/fusesoc-add-files.py
description: Generate a litedram memory controller
usage: |
litedram_gen adds the pre-generated LiteX LiteDRAM memory controller
based on the board type.

Parameters:
board: The board type (arty, nexys_video)

@ -45,6 +45,8 @@ filesets:
- wishbone_debug_master.vhdl
- wishbone_bram_wrapper.vhdl
- soc.vhdl
- xics.vhdl
- syscon.vhdl
file_type : vhdlSource-2008

fpga:
@ -54,7 +56,6 @@ filesets:
- fpga/pp_fifo.vhd
- fpga/pp_soc_uart.vhd
- fpga/pp_utilities.vhd
- fpga/toplevel.vhdl
- fpga/firmware.hex : {copyto : firmware.hex, file_type : user}
file_type : vhdlSource-2008

@ -70,21 +71,28 @@ filesets:
files:
- fpga/nexys_a7.xdc : {file_type : xdc}
- fpga/clk_gen_plle2.vhd : {file_type : vhdlSource-2008}
- fpga/top-generic.vhdl : {file_type : vhdlSource-2008}

nexys_video:
files:
- fpga/nexys-video.xdc : {file_type : xdc}
- fpga/clk_gen_plle2.vhd : {file_type : vhdlSource-2008}
- fpga/top-nexys-video.vhdl : {file_type : vhdlSource-2008}

arty_a7:
files:
- fpga/arty_a7.xdc : {file_type : xdc}
- fpga/clk_gen_plle2.vhd : {file_type : vhdlSource-2008}
- fpga/top-arty.vhdl : {file_type : vhdlSource-2008}

cmod_a7-35:
files:
- fpga/cmod_a7-35.xdc : {file_type : xdc}
- fpga/clk_gen_mcmm.vhd : {file_type : vhdlSource-2008}
- fpga/top-generic.vhdl : {file_type : vhdlSource-2008}

litedram:
depend : [":microwatt:litedram"]

targets:
nexys_a7:
@ -100,7 +108,7 @@ targets:
vivado: {part : xc7a100tcsg324-1}
toplevel : toplevel

nexys_video:
nexys_video-nodram:
default_tool: vivado
filesets: [core, nexys_video, soc, fpga, debug_xilinx]
parameters :
@ -113,7 +121,20 @@ targets:
vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel

arty_a7-35:
nexys_video:
default_tool: vivado
filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram]
parameters:
- memory_size
- ram_init_file
- use_litedram=true
- disable_flatten_core
generate: [dram_nexys_video]
tools:
vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel

arty_a7-35-nodram:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx]
parameters :
@ -126,7 +147,20 @@ targets:
vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel

arty_a7-100:
arty_a7-35:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram]
parameters :
- memory_size
- ram_init_file
- use_litedram=true
- disable_flatten_core
generate: [dram_arty]
tools:
vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel

arty_a7-100-nodram:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx]
parameters :
@ -139,6 +173,19 @@ targets:
vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel

arty_a7-100:
default_tool: vivado
filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram]
parameters:
- memory_size
- ram_init_file
- use_litedram=true
- disable_flatten_core
generate: [dram_arty]
tools:
vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel

cmod_a7-35:
default_tool: vivado
filesets: [core, cmod_a7-35, soc, fpga, debug_xilinx]
@ -159,6 +206,15 @@ targets:
vivado: {pnr : none}
toplevel: core

generate:
dram_arty:
generator: litedram_gen
parameters: {board : arty}

dram_nexys_video:
generator: litedram_gen
parameters: {board : nexys-video}

parameters:
memory_size:
datatype : int
@ -186,10 +242,16 @@ parameters:
datatype : int
description : Generated system clock frequency in HZ (for top-generic based boards)
paramtype : generic
default : 50000000
default : 100000000

disable_flatten_core:
datatype : bool
description : Prevent Vivado from flattening the main core components
paramtype : generic
default : false

use_litedram:
datatype : bool
description : Use liteDRAM
paramtype : generic
default : false

@ -9,7 +9,7 @@ CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy

CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections
CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I../include
ASFLAGS = $(CFLAGS)
LDFLAGS = -T powerpc.lds


@ -5,3 +5,8 @@ all: mw_debug
mw_debug: mw_debug.c
$(CC) -o $@ $^ -lurjtag

clean:
rm -f mw_debug
distclean:
rm -f *~


@ -392,7 +392,7 @@ static void core_start(void)

static void core_reset(void)
{
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_START), "resetting core");
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_RESET), "resetting core");
}

static void core_step(void)

@ -10,24 +10,44 @@ use work.common.all;
use work.wishbone_types.all;


-- 0x00000000: Main memory (1 MB)
-- 0xc0002000: UART0 (for host communication)
-- Memory map:
--
-- 0x00000000: Block RAM (MEMORY_SIZE) or DRAM depending on syscon
-- 0x40000000: DRAM (when present)
-- 0xc0000000: SYSCON
-- 0xc0002000: UART0
-- 0xc0004000: XICS ICP
-- 0xc0100000: DRAM CSRs
-- 0xf0000000: Block RAM (aliased & repeated)
-- 0xffff0000: DRAM init code (if any)

entity soc is
generic (
MEMORY_SIZE : positive;
RAM_INIT_FILE : string;
RESET_LOW : boolean;
CLK_FREQ : positive;
SIM : boolean;
DISABLE_FLATTEN_CORE : boolean := false
DISABLE_FLATTEN_CORE : boolean := false;
HAS_DRAM : boolean := false;
DRAM_SIZE : integer := 0
);
port(
rst : in std_ulogic;
system_clk : in std_ulogic;

-- DRAM controller signals
wb_dram_in : out wishbone_master_out;
wb_dram_out : in wishbone_slave_out;
wb_dram_csr : out std_ulogic;
wb_dram_init : out std_ulogic;

-- UART0 signals:
uart0_txd : out std_ulogic;
uart0_rxd : in std_ulogic
uart0_rxd : in std_ulogic;

-- DRAM controller signals
alt_reset : in std_ulogic
);
end entity soc;

@ -51,6 +71,12 @@ architecture behaviour of soc is
signal wb_master_in : wishbone_slave_out;
signal wb_master_out : wishbone_master_out;

-- Syscon signals
signal dram_at_0 : std_ulogic;
signal core_reset : std_ulogic;
signal wb_syscon_in : wishbone_master_out;
signal wb_syscon_out : wishbone_slave_out;

-- UART0 signals:
signal wb_uart0_in : wishbone_master_out;
signal wb_uart0_out : wishbone_slave_out;
@ -89,11 +115,13 @@ begin
processor: entity work.core
generic map(
SIM => SIM,
DISABLE_FLATTEN => DISABLE_FLATTEN_CORE
DISABLE_FLATTEN => DISABLE_FLATTEN_CORE,
ALT_RESET_ADDRESS => (15 downto 0 => '0', others => '1')
)
port map(
clk => system_clk,
rst => rst,
rst => rst or core_reset,
alt_reset => alt_reset,
wishbone_insn_in => wishbone_icore_in,
wishbone_insn_out => wishbone_icore_out,
wishbone_data_in => wishbone_dcore_in,
@ -127,26 +155,40 @@ begin
);

-- Wishbone slaves address decoder & mux
slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out)
slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out, wb_dram_out, wb_syscon_out)
-- Selected slave
type slave_type is (SLAVE_UART_0,
SLAVE_MEMORY,
type slave_type is (SLAVE_SYSCON,
SLAVE_UART,
SLAVE_BRAM,
SLAVE_DRAM,
SLAVE_DRAM_INIT,
SLAVE_DRAM_CSR,
SLAVE_ICP_0,
SLAVE_NONE);
variable slave : slave_type;
begin
-- Simple address decoder.
slave := SLAVE_NONE;
if wb_master_out.adr(31 downto 24) = x"00" then
slave := SLAVE_MEMORY;
elsif wb_master_out.adr(31 downto 24) = x"c0" then
if wb_master_out.adr(23 downto 12) = x"002" then
slave := SLAVE_UART_0;
end if;
if wb_master_out.adr(23 downto 12) = x"004" then
-- Simple address decoder. Ignore top bits to save silicon for now
slave := SLAVE_NONE;
if std_match(wb_master_out.adr, x"0-------") then
slave := SLAVE_DRAM when HAS_DRAM and dram_at_0 = '1' else
SLAVE_BRAM;
elsif std_match(wb_master_out.adr, x"FFFF----") then
slave := SLAVE_DRAM_INIT;
elsif std_match(wb_master_out.adr, x"F-------") then
slave := SLAVE_BRAM;
elsif std_match(wb_master_out.adr, x"4-------") and HAS_DRAM then
slave := SLAVE_DRAM;
elsif std_match(wb_master_out.adr, x"C0000---") then
slave := SLAVE_SYSCON;
elsif std_match(wb_master_out.adr, x"C0002---") then
slave := SLAVE_UART;
elsif std_match(wb_master_out.adr, x"C01-----") then
slave := SLAVE_DRAM_CSR;
elsif std_match(wb_master_out.adr, x"C0004---") then
slave := SLAVE_ICP_0;
end if;
end if;

-- Wishbone muxing. Defaults:
wb_bram_in <= wb_master_out;
@ -159,11 +201,32 @@ begin
wb_xics0_in.adr <= (others => '0');
wb_xics0_in.adr(7 downto 0) <= wb_master_out.adr(7 downto 0);
wb_xics0_in.cyc <= '0';

wb_dram_in <= wb_master_out;
wb_dram_in.cyc <= '0';
wb_dram_csr <= '0';
wb_dram_init <= '0';
wb_syscon_in <= wb_master_out;
wb_syscon_in.cyc <= '0';
case slave is
when SLAVE_MEMORY =>
when SLAVE_BRAM =>
wb_bram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_bram_out;
when SLAVE_UART_0 =>
when SLAVE_DRAM =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
when SLAVE_DRAM_INIT =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
wb_dram_init <= '1';
when SLAVE_DRAM_CSR =>
wb_dram_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_dram_out;
wb_dram_csr <= '1';
when SLAVE_SYSCON =>
wb_syscon_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_syscon_out;
when SLAVE_UART =>
wb_uart0_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_uart0_out;
when SLAVE_ICP_0 =>
@ -176,6 +239,25 @@ begin
end case;
end process slave_intercon;

-- Syscon slave
syscon0: entity work.syscon
generic map(
HAS_UART => true,
HAS_DRAM => HAS_DRAM,
BRAM_SIZE => MEMORY_SIZE,
DRAM_SIZE => DRAM_SIZE,
CLK_FREQ => CLK_FREQ
)
port map(
clk => system_clk,
rst => rst,
wishbone_in => wb_syscon_in,
wishbone_out => wb_syscon_out,
dram_at_0 => dram_at_0,
core_reset => core_reset,
soc_reset => open -- XXX TODO
);

-- Simulated memory and UART

-- UART0 wishbone slave

@ -0,0 +1,136 @@
-- syscon module, a bunch of misc global system control MMIO registers
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.wishbone_types.all;

entity syscon is
generic (
SIG_VALUE : std_ulogic_vector(63 downto 0) := x"f00daa5500010001";
CLK_FREQ : integer;
HAS_UART : boolean;
HAS_DRAM : boolean;
BRAM_SIZE : integer;
DRAM_SIZE : integer
);
port (
clk : in std_ulogic;
rst : in std_ulogic;

-- Wishbone ports:
wishbone_in : in wishbone_master_out;
wishbone_out : out wishbone_slave_out;

-- System control ports
dram_at_0 : out std_ulogic;
core_reset : out std_ulogic;
soc_reset : out std_ulogic
);
end entity syscon;


architecture behaviour of syscon is
-- Register address bits
constant SYS_REG_BITS : positive := 3;

-- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "100";
constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "101";

-- INFO register bits
constant SYS_REG_INFO_HAS_UART : integer := 0;
constant SYS_REG_INFO_HAS_DRAM : integer := 1;

-- BRAMINFO contains the BRAM size in the bottom 52 bits
-- DRAMINFO contains the DRAM size if any in the bottom 52 bits
-- (both have reserved top bits for future use)
-- CLKINFO contains the CLK frequency is HZ in the bottom 40 bits

-- CTRL register bits
constant SYS_REG_CTRL_BITS : positive := 3;
constant SYS_REG_CTRL_DRAM_AT_0 : integer := 0;
constant SYS_REG_CTRL_CORE_RESET : integer := 1;
constant SYS_REG_CTRL_SOC_RESET : integer := 2;

-- Ctrl register
signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
signal reg_ctrl_out : std_ulogic_vector(63 downto 0);

-- Others
signal reg_info : std_ulogic_vector(63 downto 0);
signal reg_braminfo : std_ulogic_vector(63 downto 0);
signal reg_draminfo : std_ulogic_vector(63 downto 0);
signal reg_clkinfo : std_ulogic_vector(63 downto 0);
signal info_has_dram : std_ulogic;
signal info_has_uart : std_ulogic;
signal info_clk : std_ulogic_vector(39 downto 0);
begin

-- Generated output signals
dram_at_0 <= reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
soc_reset <= reg_ctrl(SYS_REG_CTRL_SOC_RESET);
core_reset <= reg_ctrl(SYS_REG_CTRL_CORE_RESET);

-- All register accesses are single cycle
wishbone_out.ack <= wishbone_in.cyc and wishbone_in.stb;
wishbone_out.stall <= '0';

-- Info register is hard wired
info_has_uart <= '1' when HAS_UART else '0';
info_has_dram <= '1' when HAS_DRAM else '0';
info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
reg_info <= (0 => info_has_uart,
1 => info_has_dram,
others => '0');
reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
reg_draminfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_SIZE, 52)) when HAS_DRAM
else (others => '0');
reg_clkinfo <= (39 downto 0 => info_clk,
others => '0');

-- Control register read composition
reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);

-- Register read mux
with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select wishbone_out.dat <=
SIG_VALUE when SYS_REG_SIG,
reg_info when SYS_REG_INFO,
reg_braminfo when SYS_REG_BRAMINFO,
reg_draminfo when SYS_REG_DRAMINFO,
reg_clkinfo when SYS_REG_CLKINFO,
reg_ctrl_out when SYS_REG_CTRL,
(others => '0') when others;

-- Register writes
regs_write: process(clk)
begin
if rising_edge(clk) then
if (rst) then
reg_ctrl <= (others => '0');
else
if wishbone_in.cyc and wishbone_in.stb and wishbone_in.we then
if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL then
reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
end if;
end if;

-- Reset auto-clear
if reg_ctrl(SYS_REG_CTRL_SOC_RESET) = '1' then
reg_ctrl(SYS_REG_CTRL_SOC_RESET) <= '0';
end if;
if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
end if;
end if;
end if;
end process;

end architecture behaviour;

@ -9,7 +9,7 @@ CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy

CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I ../../hello_world
CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I ../../hello_world -I ../../include
ASFLAGS = $(CFLAGS)
LDFLAGS = -T powerpc.lds


Loading…
Cancel
Save