litedram: Add simulation support
This adds a simulated litedram model along with the necessary Makefile gunk to verilate it and wrap it for use by ghdl. The core_dram_tb test bench is a variant of core_tb with LiteDRAM simulated. It's not built by default, an explicit make core_dram_tb is necessary as to not require verilator to be installed for the normal build process (also it's slow'ish). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>pull/190/head
parent
42e138e539
commit
6fe077910b
@ -0,0 +1,114 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.common.all;
|
||||||
|
use work.wishbone_types.all;
|
||||||
|
|
||||||
|
entity core_dram_tb is
|
||||||
|
end core_dram_tb;
|
||||||
|
|
||||||
|
architecture behave of core_dram_tb is
|
||||||
|
signal clk, rst: std_logic;
|
||||||
|
signal system_clk, soc_rst : std_ulogic;
|
||||||
|
|
||||||
|
-- testbench signals
|
||||||
|
constant clk_period : time := 10 ns;
|
||||||
|
|
||||||
|
-- Sim DRAM
|
||||||
|
signal wb_dram_in : wishbone_master_out;
|
||||||
|
signal wb_dram_out : wishbone_slave_out;
|
||||||
|
signal wb_dram_ctrl_in : wb_io_master_out;
|
||||||
|
signal wb_dram_ctrl_out : wb_io_slave_out;
|
||||||
|
signal wb_dram_is_csr : std_ulogic;
|
||||||
|
signal wb_dram_is_init : std_ulogic;
|
||||||
|
signal core_alt_reset : std_ulogic;
|
||||||
|
begin
|
||||||
|
|
||||||
|
soc0: entity work.soc
|
||||||
|
generic map(
|
||||||
|
SIM => true,
|
||||||
|
MEMORY_SIZE => (384*1024),
|
||||||
|
RAM_INIT_FILE => "main_ram.bin",
|
||||||
|
RESET_LOW => false,
|
||||||
|
HAS_DRAM => true,
|
||||||
|
DRAM_SIZE => 256 * 1024 * 1024,
|
||||||
|
CLK_FREQ => 100000000
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
rst => soc_rst,
|
||||||
|
system_clk => system_clk,
|
||||||
|
uart0_rxd => '0',
|
||||||
|
uart0_txd => open,
|
||||||
|
wb_dram_in => wb_dram_in,
|
||||||
|
wb_dram_out => wb_dram_out,
|
||||||
|
wb_dram_ctrl_in => wb_dram_ctrl_in,
|
||||||
|
wb_dram_ctrl_out => wb_dram_ctrl_out,
|
||||||
|
wb_dram_is_csr => wb_dram_is_csr,
|
||||||
|
wb_dram_is_init => wb_dram_is_init,
|
||||||
|
alt_reset => core_alt_reset
|
||||||
|
);
|
||||||
|
|
||||||
|
dram: entity work.litedram_wrapper
|
||||||
|
generic map(
|
||||||
|
DRAM_ABITS => 24,
|
||||||
|
DRAM_ALINES => 1
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk_in => clk,
|
||||||
|
rst => rst,
|
||||||
|
system_clk => system_clk,
|
||||||
|
system_reset => soc_rst,
|
||||||
|
core_alt_reset => core_alt_reset,
|
||||||
|
pll_locked => open,
|
||||||
|
|
||||||
|
wb_in => wb_dram_in,
|
||||||
|
wb_out => wb_dram_out,
|
||||||
|
wb_ctrl_in => wb_dram_ctrl_in,
|
||||||
|
wb_ctrl_out => wb_dram_ctrl_out,
|
||||||
|
wb_ctrl_is_csr => wb_dram_is_csr,
|
||||||
|
wb_ctrl_is_init => wb_dram_is_init,
|
||||||
|
|
||||||
|
serial_tx => open,
|
||||||
|
serial_rx => '1',
|
||||||
|
|
||||||
|
init_done => open,
|
||||||
|
init_error => open,
|
||||||
|
|
||||||
|
ddram_a => open,
|
||||||
|
ddram_ba => open,
|
||||||
|
ddram_ras_n => open,
|
||||||
|
ddram_cas_n => open,
|
||||||
|
ddram_we_n => open,
|
||||||
|
ddram_cs_n => open,
|
||||||
|
ddram_dm => open,
|
||||||
|
ddram_dq => open,
|
||||||
|
ddram_dqs_p => open,
|
||||||
|
ddram_dqs_n => open,
|
||||||
|
ddram_clk_p => open,
|
||||||
|
ddram_clk_n => open,
|
||||||
|
ddram_cke => open,
|
||||||
|
ddram_odt => open,
|
||||||
|
ddram_reset_n => open
|
||||||
|
);
|
||||||
|
|
||||||
|
clk_process: process
|
||||||
|
begin
|
||||||
|
clk <= '0';
|
||||||
|
wait for clk_period/2;
|
||||||
|
clk <= '1';
|
||||||
|
wait for clk_period/2;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
rst_process: process
|
||||||
|
begin
|
||||||
|
rst <= '1';
|
||||||
|
wait for 10*clk_period;
|
||||||
|
rst <= '0';
|
||||||
|
wait;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
jtag: entity work.sim_jtag;
|
||||||
|
|
||||||
|
end;
|
@ -0,0 +1,10 @@
|
|||||||
|
OPT_FAST=-O3 -fstrict-aliasing
|
||||||
|
OPT_SLOW=-O3 -fstrict-aliasing
|
||||||
|
|
||||||
|
top_all: top_all2
|
||||||
|
|
||||||
|
include Vlitedram_core.mk
|
||||||
|
|
||||||
|
top_all2: default $(VK_GLOBAL_OBJS)
|
||||||
|
|
||||||
|
.PHONY: top_all top_all2
|
@ -0,0 +1,214 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
|
||||||
|
package sim_litedram is
|
||||||
|
-- WB req format:
|
||||||
|
-- 73 .. 71 : cti(2..0)
|
||||||
|
-- 70 .. 69 : bte(1..0)
|
||||||
|
-- 68 .. 65 : sel(3..0)
|
||||||
|
-- 64 : we
|
||||||
|
-- 63 : stb
|
||||||
|
-- 62 : cyc
|
||||||
|
-- 61 .. 32 : addr(29..0)
|
||||||
|
-- 31 .. 0 : write_data(31..0)
|
||||||
|
--
|
||||||
|
procedure litedram_set_wb(req : in std_ulogic_vector(73 downto 0));
|
||||||
|
attribute foreign of litedram_set_wb : procedure is "VHPIDIRECT litedram_set_wb";
|
||||||
|
|
||||||
|
-- WB rsp format:
|
||||||
|
-- 35 : init_error;
|
||||||
|
-- 34 : init_done;
|
||||||
|
-- 33 : err
|
||||||
|
-- 32 : ack
|
||||||
|
-- 31 .. 0 : read_data(31..0)
|
||||||
|
--
|
||||||
|
procedure litedram_get_wb(rsp : out std_ulogic_vector(35 downto 0));
|
||||||
|
attribute foreign of litedram_get_wb : procedure is "VHPIDIRECT litedram_get_wb";
|
||||||
|
|
||||||
|
-- User req format:
|
||||||
|
-- 171 : cmd_valid
|
||||||
|
-- 170 : cmd_we
|
||||||
|
-- 169 : wdata_valid
|
||||||
|
-- 168 : rdata_ready
|
||||||
|
-- 167 .. 144 : cmd_addr(23..0)
|
||||||
|
-- 143 .. 128 : wdata_we(15..0)
|
||||||
|
-- 127 .. 0 : wdata_data(127..0)
|
||||||
|
--
|
||||||
|
procedure litedram_set_user(req: in std_ulogic_vector(171 downto 0));
|
||||||
|
attribute foreign of litedram_set_user : procedure is "VHPIDIRECT litedram_set_user";
|
||||||
|
|
||||||
|
-- User rsp format:
|
||||||
|
-- 130 : cmd_ready
|
||||||
|
-- 129 : wdata_ready
|
||||||
|
-- 128 : rdata_valid
|
||||||
|
-- 127 .. 0 : rdata_data(127..0)
|
||||||
|
|
||||||
|
procedure litedram_get_user(req: in std_ulogic_vector(130 downto 0));
|
||||||
|
attribute foreign of litedram_get_user : procedure is "VHPIDIRECT litedram_get_user";
|
||||||
|
|
||||||
|
procedure litedram_clock;
|
||||||
|
attribute foreign of litedram_clock : procedure is "VHPIDIRECT litedram_clock";
|
||||||
|
|
||||||
|
procedure litedram_init(trace: integer);
|
||||||
|
attribute foreign of litedram_init : procedure is "VHPIDIRECT litedram_init";
|
||||||
|
end sim_litedram;
|
||||||
|
|
||||||
|
package body sim_litedram is
|
||||||
|
procedure litedram_set_wb(req : in std_ulogic_vector(73 downto 0)) is
|
||||||
|
begin
|
||||||
|
assert false report "VHPI" severity failure;
|
||||||
|
end procedure;
|
||||||
|
procedure litedram_get_wb(rsp : out std_ulogic_vector(35 downto 0)) is
|
||||||
|
begin
|
||||||
|
assert false report "VHPI" severity failure;
|
||||||
|
end procedure;
|
||||||
|
procedure litedram_set_user(req: in std_ulogic_vector(171 downto 0)) is
|
||||||
|
begin
|
||||||
|
assert false report "VHPI" severity failure;
|
||||||
|
end procedure;
|
||||||
|
procedure litedram_get_user(req: in std_ulogic_vector(130 downto 0)) is
|
||||||
|
begin
|
||||||
|
assert false report "VHPI" severity failure;
|
||||||
|
end procedure;
|
||||||
|
procedure litedram_clock is
|
||||||
|
begin
|
||||||
|
assert false report "VHPI" severity failure;
|
||||||
|
end procedure;
|
||||||
|
procedure litedram_init(trace: integer) is
|
||||||
|
begin
|
||||||
|
assert false report "VHPI" severity failure;
|
||||||
|
end procedure;
|
||||||
|
end sim_litedram;
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.sim_litedram.all;
|
||||||
|
|
||||||
|
entity litedram_core is
|
||||||
|
port(
|
||||||
|
clk : in std_ulogic;
|
||||||
|
rst : in std_ulogic;
|
||||||
|
pll_locked : out std_ulogic;
|
||||||
|
ddram_a : out std_ulogic_vector(0 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;
|
||||||
|
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
|
||||||
|
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
|
||||||
|
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
|
||||||
|
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
|
||||||
|
wb_ctrl_cyc : in std_ulogic;
|
||||||
|
wb_ctrl_stb : in std_ulogic;
|
||||||
|
wb_ctrl_ack : out std_ulogic;
|
||||||
|
wb_ctrl_we : in std_ulogic;
|
||||||
|
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
|
||||||
|
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
|
||||||
|
wb_ctrl_err : 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(23 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 entity litedram_core;
|
||||||
|
|
||||||
|
architecture behaviour of litedram_core is
|
||||||
|
signal idone : std_ulogic := '0';
|
||||||
|
signal ierr : std_ulogic := '0';
|
||||||
|
signal old_wb_cyc : std_ulogic := '1';
|
||||||
|
begin
|
||||||
|
user_rst <= rst;
|
||||||
|
user_clk <= clk;
|
||||||
|
pll_locked <= '1';
|
||||||
|
init_done <= idone;
|
||||||
|
init_error <= ierr;
|
||||||
|
|
||||||
|
poll: process(user_clk)
|
||||||
|
procedure send_signals is
|
||||||
|
begin
|
||||||
|
litedram_set_wb(wb_ctrl_cti & wb_ctrl_bte &
|
||||||
|
wb_ctrl_sel & wb_ctrl_we &
|
||||||
|
wb_ctrl_stb & wb_ctrl_cyc &
|
||||||
|
wb_ctrl_adr & wb_ctrl_dat_w);
|
||||||
|
litedram_set_user(user_port_native_0_cmd_valid &
|
||||||
|
user_port_native_0_cmd_we &
|
||||||
|
user_port_native_0_wdata_valid &
|
||||||
|
user_port_native_0_rdata_ready &
|
||||||
|
user_port_native_0_cmd_addr &
|
||||||
|
user_port_native_0_wdata_we &
|
||||||
|
user_port_native_0_wdata_data);
|
||||||
|
end procedure;
|
||||||
|
|
||||||
|
procedure recv_signals is
|
||||||
|
variable wb_response : std_ulogic_vector(35 downto 0);
|
||||||
|
variable ur_response : std_ulogic_vector(130 downto 0);
|
||||||
|
begin
|
||||||
|
litedram_get_wb(wb_response);
|
||||||
|
wb_ctrl_dat_r <= wb_response(31 downto 0);
|
||||||
|
wb_ctrl_ack <= wb_response(32);
|
||||||
|
wb_ctrl_err <= wb_response(33);
|
||||||
|
idone <= wb_response(34);
|
||||||
|
ierr <= wb_response(35);
|
||||||
|
litedram_get_user(ur_response);
|
||||||
|
user_port_native_0_cmd_ready <= ur_response(130);
|
||||||
|
user_port_native_0_wdata_ready <= ur_response(129);
|
||||||
|
user_port_native_0_rdata_valid <= ur_response(128);
|
||||||
|
user_port_native_0_rdata_data <= ur_response(127 downto 0);
|
||||||
|
end procedure;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if rising_edge(user_clk) then
|
||||||
|
|
||||||
|
send_signals;
|
||||||
|
recv_signals;
|
||||||
|
-- Then generate a clock cycle ( 0->1 then 1->0 )
|
||||||
|
litedram_clock;
|
||||||
|
recv_signals;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if falling_edge(user_clk) then
|
||||||
|
send_signals;
|
||||||
|
recv_signals;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.sim_litedram.all;
|
||||||
|
|
||||||
|
entity litedram_trace_stub is
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture behaviour of litedram_trace_stub is
|
||||||
|
begin
|
||||||
|
process
|
||||||
|
begin
|
||||||
|
litedram_init(1);
|
||||||
|
wait;
|
||||||
|
end process;
|
||||||
|
end architecture;
|
@ -0,0 +1,198 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
#include "sim_vhpi_c.h"
|
||||||
|
#include "Vlitedram_core.h"
|
||||||
|
#include "verilated_vcd_c.h"
|
||||||
|
|
||||||
|
static Vlitedram_core *v;
|
||||||
|
vluint64_t main_time = 0;
|
||||||
|
|
||||||
|
#if VM_TRACE
|
||||||
|
VerilatedVcdC *tfp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void cleanup(void)
|
||||||
|
{
|
||||||
|
#if VM_TRACE
|
||||||
|
if (tfp) {
|
||||||
|
tfp->flush();
|
||||||
|
tfp->close();
|
||||||
|
delete tfp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void check_init(bool traces)
|
||||||
|
{
|
||||||
|
if (v)
|
||||||
|
return;
|
||||||
|
// XX Catch exceptions ?
|
||||||
|
v = new Vlitedram_core;
|
||||||
|
if (!v) {
|
||||||
|
fprintf(stderr, "Failure allocating litedram core\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#if VM_TRACE
|
||||||
|
if (traces) {
|
||||||
|
// init trace dump
|
||||||
|
Verilated::traceEverOn(true);
|
||||||
|
tfp = new VerilatedVcdC;
|
||||||
|
v->trace(tfp, 99);
|
||||||
|
tfp->open("litedram.vcd");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
atexit(cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char get_bit(unsigned char **p)
|
||||||
|
{
|
||||||
|
unsigned char b = **p;
|
||||||
|
|
||||||
|
*p = *p + 1;
|
||||||
|
|
||||||
|
return b == vhpi1 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t get_bits(unsigned char **p, int len)
|
||||||
|
{
|
||||||
|
uint64_t r = 0;
|
||||||
|
|
||||||
|
while(len--)
|
||||||
|
r = (r << 1) | get_bit(p);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_bit(unsigned char **p, int bit)
|
||||||
|
{
|
||||||
|
**p = bit ? vhpi1 : vhpi0;
|
||||||
|
*p = *p + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_bits(unsigned char **p, uint64_t val, int len)
|
||||||
|
{
|
||||||
|
while(len--)
|
||||||
|
set_bit(p, (val >> len) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double sc_time_stamp(void)
|
||||||
|
{
|
||||||
|
return main_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define check_size(s, exp) \
|
||||||
|
do { \
|
||||||
|
int __s = (s); \
|
||||||
|
int __e = (exp); \
|
||||||
|
if (__s != __e) \
|
||||||
|
fprintf(stderr, "WARNING: %s exp %d got %d\n", __func__, __e, __s); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
static void do_eval(void)
|
||||||
|
{
|
||||||
|
v->eval();
|
||||||
|
#if VM_TRACE
|
||||||
|
if (tfp)
|
||||||
|
tfp->dump((double) main_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void litedram_set_wb(unsigned char *req)
|
||||||
|
{
|
||||||
|
unsigned char *orig = req;
|
||||||
|
|
||||||
|
check_init(false);
|
||||||
|
|
||||||
|
v->wb_ctrl_cti = get_bits(&req, 3);
|
||||||
|
v->wb_ctrl_bte = get_bits(&req, 2);
|
||||||
|
v->wb_ctrl_sel = get_bits(&req, 4);
|
||||||
|
v->wb_ctrl_we = get_bit(&req);
|
||||||
|
v->wb_ctrl_stb = get_bit(&req);
|
||||||
|
v->wb_ctrl_cyc = get_bit(&req);
|
||||||
|
v->wb_ctrl_adr = get_bits(&req, 30);
|
||||||
|
v->wb_ctrl_dat_w = get_bits(&req, 32);
|
||||||
|
|
||||||
|
check_size(req - orig, 74);
|
||||||
|
|
||||||
|
do_eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void litedram_get_wb(unsigned char *req)
|
||||||
|
{
|
||||||
|
unsigned char *orig = req;
|
||||||
|
|
||||||
|
check_init(false);
|
||||||
|
|
||||||
|
set_bit(&req, v->init_error);
|
||||||
|
set_bit(&req, v->init_done);
|
||||||
|
set_bit(&req, v->wb_ctrl_err);
|
||||||
|
set_bit(&req, v->wb_ctrl_ack);
|
||||||
|
set_bits(&req, v->wb_ctrl_dat_r, 32);
|
||||||
|
|
||||||
|
check_size(req - orig, 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void litedram_set_user(unsigned char *req)
|
||||||
|
{
|
||||||
|
unsigned char *orig = req;
|
||||||
|
|
||||||
|
check_init(false);
|
||||||
|
|
||||||
|
v->user_port_native_0_cmd_valid = get_bit(&req);
|
||||||
|
v->user_port_native_0_cmd_we = get_bit(&req);
|
||||||
|
v->user_port_native_0_wdata_valid = get_bit(&req);
|
||||||
|
v->user_port_native_0_rdata_ready = get_bit(&req);
|
||||||
|
v->user_port_native_0_cmd_addr = get_bits(&req, 24);
|
||||||
|
v->user_port_native_0_wdata_we = get_bits(&req, 16);
|
||||||
|
v->user_port_native_0_wdata_data[3] = get_bits(&req, 32);
|
||||||
|
v->user_port_native_0_wdata_data[2] = get_bits(&req, 32);
|
||||||
|
v->user_port_native_0_wdata_data[1] = get_bits(&req, 32);
|
||||||
|
v->user_port_native_0_wdata_data[0] = get_bits(&req, 32);
|
||||||
|
|
||||||
|
check_size(req - orig, 172);
|
||||||
|
|
||||||
|
do_eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void litedram_get_user(unsigned char *req)
|
||||||
|
{
|
||||||
|
unsigned char *orig = req;
|
||||||
|
|
||||||
|
check_init(false);
|
||||||
|
|
||||||
|
set_bit(&req, v->user_port_native_0_cmd_ready);
|
||||||
|
set_bit(&req, v->user_port_native_0_wdata_ready);
|
||||||
|
set_bit(&req, v->user_port_native_0_rdata_valid);
|
||||||
|
set_bits(&req, v->user_port_native_0_rdata_data[3], 32);
|
||||||
|
set_bits(&req, v->user_port_native_0_rdata_data[2], 32);
|
||||||
|
set_bits(&req, v->user_port_native_0_rdata_data[1], 32);
|
||||||
|
set_bits(&req, v->user_port_native_0_rdata_data[0], 32);
|
||||||
|
|
||||||
|
check_size(req - orig, 131);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void litedram_clock(void)
|
||||||
|
{
|
||||||
|
check_init(false);
|
||||||
|
|
||||||
|
v->clk = 1;
|
||||||
|
do_eval();
|
||||||
|
main_time++;
|
||||||
|
v->clk = 0;
|
||||||
|
do_eval();
|
||||||
|
main_time++;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void litedram_init(int trace_on)
|
||||||
|
{
|
||||||
|
check_init(!!trace_on);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
|
# License: BSD
|
||||||
|
|
||||||
|
{
|
||||||
|
# General ------------------------------------------------------------------
|
||||||
|
"cpu": "None", # Type of CPU used for init/calib (vexriscv, lm32)
|
||||||
|
"cpu_variant":"minimal",
|
||||||
|
"speedgrade": -1, # FPGA speedgrade
|
||||||
|
"memtype": "DDR3", # DRAM type
|
||||||
|
"sim" : "True",
|
||||||
|
|
||||||
|
# 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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
none
|
@ -1,284 +0,0 @@
|
|||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use std.textio.all;
|
|
||||||
|
|
||||||
library work;
|
|
||||||
use work.wishbone_types.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_ctrl_in : in wb_io_master_out;
|
|
||||||
wb_ctrl_out : out wb_io_slave_out;
|
|
||||||
wb_ctrl_is_csr : in std_ulogic;
|
|
||||||
wb_ctrl_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;
|
|
||||||
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
|
|
||||||
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
|
|
||||||
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
|
|
||||||
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
|
|
||||||
wb_ctrl_cyc : in std_ulogic;
|
|
||||||
wb_ctrl_stb : in std_ulogic;
|
|
||||||
wb_ctrl_ack : out std_ulogic;
|
|
||||||
wb_ctrl_we : in std_ulogic;
|
|
||||||
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
|
|
||||||
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
|
|
||||||
wb_ctrl_err : 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 wb_ctrl_adr : std_ulogic_vector(29 downto 0);
|
|
||||||
signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0);
|
|
||||||
signal wb_ctrl_dat_r : std_ulogic_vector(31 downto 0);
|
|
||||||
signal wb_ctrl_sel : std_ulogic_vector(3 downto 0);
|
|
||||||
signal wb_ctrl_cyc : std_ulogic;
|
|
||||||
signal wb_ctrl_stb : std_ulogic;
|
|
||||||
signal wb_ctrl_ack : std_ulogic;
|
|
||||||
signal wb_ctrl_we : std_ulogic;
|
|
||||||
|
|
||||||
signal wb_init_in : wb_io_master_out;
|
|
||||||
signal wb_init_out : wb_io_slave_out;
|
|
||||||
|
|
||||||
type state_t is (CMD, MWRITE, MREAD);
|
|
||||||
signal state : state_t;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
-- alternate core reset address set when DRAM is not initialized.
|
|
||||||
core_alt_reset <= not init_done;
|
|
||||||
|
|
||||||
-- Init code BRAM memory slave
|
|
||||||
init_ram_0: entity work.dram_init_mem
|
|
||||||
port map(
|
|
||||||
clk => system_clk,
|
|
||||||
wb_in => wb_init_in,
|
|
||||||
wb_out => wb_init_out
|
|
||||||
);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Control bus wishbone: This muxes the wishbone to the CSRs
|
|
||||||
-- and an internal small one to the init BRAM
|
|
||||||
--
|
|
||||||
|
|
||||||
-- Init DRAM wishbone IN signals
|
|
||||||
wb_init_in.adr <= wb_ctrl_in.adr;
|
|
||||||
wb_init_in.dat <= wb_ctrl_in.dat;
|
|
||||||
wb_init_in.sel <= wb_ctrl_in.sel;
|
|
||||||
wb_init_in.we <= wb_ctrl_in.we;
|
|
||||||
wb_init_in.stb <= wb_ctrl_in.stb;
|
|
||||||
wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;
|
|
||||||
|
|
||||||
-- DRAM CSR IN signals
|
|
||||||
wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
|
|
||||||
wb_ctrl_dat_w <= wb_ctrl_in.dat;
|
|
||||||
wb_ctrl_sel <= wb_ctrl_in.sel;
|
|
||||||
wb_ctrl_we <= wb_ctrl_in.we;
|
|
||||||
wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
|
|
||||||
wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;
|
|
||||||
|
|
||||||
-- Ctrl bus wishbone OUT signals
|
|
||||||
wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
|
|
||||||
else wb_init_out.ack;
|
|
||||||
wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
|
|
||||||
else wb_init_out.dat;
|
|
||||||
wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
|
|
||||||
'0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Data bus wishbone to LiteDRAM native port
|
|
||||||
--
|
|
||||||
-- Address bit 3 selects the top or bottom half of the data
|
|
||||||
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
|
|
||||||
--
|
|
||||||
-- XXX TODO: Figure out how to pipeline this
|
|
||||||
--
|
|
||||||
ad3 <= wb_in.adr(3);
|
|
||||||
|
|
||||||
-- Wishbone port IN signals
|
|
||||||
user_port0_cmd_valid <= wb_in.cyc and wb_in.stb 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
|
|
||||||
wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
|
|
||||||
user_port0_rdata_valid when state = MREAD else '0';
|
|
||||||
|
|
||||||
wb_out.dat <= 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;
|
|
||||||
|
|
||||||
-- DRAM user port State machine
|
|
||||||
sm: process(system_clk)
|
|
||||||
begin
|
|
||||||
|
|
||||||
if rising_edge(system_clk) then
|
|
||||||
if system_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,
|
|
||||||
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 => system_reset,
|
|
||||||
wb_ctrl_adr => wb_ctrl_adr,
|
|
||||||
wb_ctrl_dat_w => wb_ctrl_dat_w,
|
|
||||||
wb_ctrl_dat_r => wb_ctrl_dat_r,
|
|
||||||
wb_ctrl_sel => wb_ctrl_sel,
|
|
||||||
wb_ctrl_cyc => wb_ctrl_cyc,
|
|
||||||
wb_ctrl_stb => wb_ctrl_stb,
|
|
||||||
wb_ctrl_ack => wb_ctrl_ack,
|
|
||||||
wb_ctrl_we => wb_ctrl_we,
|
|
||||||
wb_ctrl_cti => "000",
|
|
||||||
wb_ctrl_bte => "00",
|
|
||||||
wb_ctrl_err => open,
|
|
||||||
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 @@
|
|||||||
|
none
|
@ -1,284 +0,0 @@
|
|||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
use std.textio.all;
|
|
||||||
|
|
||||||
library work;
|
|
||||||
use work.wishbone_types.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_ctrl_in : in wb_io_master_out;
|
|
||||||
wb_ctrl_out : out wb_io_slave_out;
|
|
||||||
wb_ctrl_is_csr : in std_ulogic;
|
|
||||||
wb_ctrl_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;
|
|
||||||
wb_ctrl_adr : in std_ulogic_vector(29 downto 0);
|
|
||||||
wb_ctrl_dat_w : in std_ulogic_vector(31 downto 0);
|
|
||||||
wb_ctrl_dat_r : out std_ulogic_vector(31 downto 0);
|
|
||||||
wb_ctrl_sel : in std_ulogic_vector(3 downto 0);
|
|
||||||
wb_ctrl_cyc : in std_ulogic;
|
|
||||||
wb_ctrl_stb : in std_ulogic;
|
|
||||||
wb_ctrl_ack : out std_ulogic;
|
|
||||||
wb_ctrl_we : in std_ulogic;
|
|
||||||
wb_ctrl_cti : in std_ulogic_vector(2 downto 0);
|
|
||||||
wb_ctrl_bte : in std_ulogic_vector(1 downto 0);
|
|
||||||
wb_ctrl_err : 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 wb_ctrl_adr : std_ulogic_vector(29 downto 0);
|
|
||||||
signal wb_ctrl_dat_w : std_ulogic_vector(31 downto 0);
|
|
||||||
signal wb_ctrl_dat_r : std_ulogic_vector(31 downto 0);
|
|
||||||
signal wb_ctrl_sel : std_ulogic_vector(3 downto 0);
|
|
||||||
signal wb_ctrl_cyc : std_ulogic;
|
|
||||||
signal wb_ctrl_stb : std_ulogic;
|
|
||||||
signal wb_ctrl_ack : std_ulogic;
|
|
||||||
signal wb_ctrl_we : std_ulogic;
|
|
||||||
|
|
||||||
signal wb_init_in : wb_io_master_out;
|
|
||||||
signal wb_init_out : wb_io_slave_out;
|
|
||||||
|
|
||||||
type state_t is (CMD, MWRITE, MREAD);
|
|
||||||
signal state : state_t;
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
-- alternate core reset address set when DRAM is not initialized.
|
|
||||||
core_alt_reset <= not init_done;
|
|
||||||
|
|
||||||
-- Init code BRAM memory slave
|
|
||||||
init_ram_0: entity work.dram_init_mem
|
|
||||||
port map(
|
|
||||||
clk => system_clk,
|
|
||||||
wb_in => wb_init_in,
|
|
||||||
wb_out => wb_init_out
|
|
||||||
);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Control bus wishbone: This muxes the wishbone to the CSRs
|
|
||||||
-- and an internal small one to the init BRAM
|
|
||||||
--
|
|
||||||
|
|
||||||
-- Init DRAM wishbone IN signals
|
|
||||||
wb_init_in.adr <= wb_ctrl_in.adr;
|
|
||||||
wb_init_in.dat <= wb_ctrl_in.dat;
|
|
||||||
wb_init_in.sel <= wb_ctrl_in.sel;
|
|
||||||
wb_init_in.we <= wb_ctrl_in.we;
|
|
||||||
wb_init_in.stb <= wb_ctrl_in.stb;
|
|
||||||
wb_init_in.cyc <= wb_ctrl_in.cyc and wb_ctrl_is_init;
|
|
||||||
|
|
||||||
-- DRAM CSR IN signals
|
|
||||||
wb_ctrl_adr <= x"0000" & wb_ctrl_in.adr(15 downto 2);
|
|
||||||
wb_ctrl_dat_w <= wb_ctrl_in.dat;
|
|
||||||
wb_ctrl_sel <= wb_ctrl_in.sel;
|
|
||||||
wb_ctrl_we <= wb_ctrl_in.we;
|
|
||||||
wb_ctrl_cyc <= wb_ctrl_in.cyc and wb_ctrl_is_csr;
|
|
||||||
wb_ctrl_stb <= wb_ctrl_in.stb and wb_ctrl_is_csr;
|
|
||||||
|
|
||||||
-- Ctrl bus wishbone OUT signals
|
|
||||||
wb_ctrl_out.ack <= wb_ctrl_ack when wb_ctrl_is_csr = '1'
|
|
||||||
else wb_init_out.ack;
|
|
||||||
wb_ctrl_out.dat <= wb_ctrl_dat_r when wb_ctrl_is_csr = '1'
|
|
||||||
else wb_init_out.dat;
|
|
||||||
wb_ctrl_out.stall <= wb_init_out.stall when wb_ctrl_is_init else
|
|
||||||
'0' when wb_ctrl_in.cyc = '0' else not wb_ctrl_ack;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Data bus wishbone to LiteDRAM native port
|
|
||||||
--
|
|
||||||
-- Address bit 3 selects the top or bottom half of the data
|
|
||||||
-- bus (64-bit wishbone vs. 128-bit DRAM interface)
|
|
||||||
--
|
|
||||||
-- XXX TODO: Figure out how to pipeline this
|
|
||||||
--
|
|
||||||
ad3 <= wb_in.adr(3);
|
|
||||||
|
|
||||||
-- Wishbone port IN signals
|
|
||||||
user_port0_cmd_valid <= wb_in.cyc and wb_in.stb 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
|
|
||||||
wb_out.ack <= user_port0_wdata_ready when state = MWRITE else
|
|
||||||
user_port0_rdata_valid when state = MREAD else '0';
|
|
||||||
|
|
||||||
wb_out.dat <= 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;
|
|
||||||
|
|
||||||
-- DRAM user port State machine
|
|
||||||
sm: process(system_clk)
|
|
||||||
begin
|
|
||||||
|
|
||||||
if rising_edge(system_clk) then
|
|
||||||
if system_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,
|
|
||||||
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 => system_reset,
|
|
||||||
wb_ctrl_adr => wb_ctrl_adr,
|
|
||||||
wb_ctrl_dat_w => wb_ctrl_dat_w,
|
|
||||||
wb_ctrl_dat_r => wb_ctrl_dat_r,
|
|
||||||
wb_ctrl_sel => wb_ctrl_sel,
|
|
||||||
wb_ctrl_cyc => wb_ctrl_cyc,
|
|
||||||
wb_ctrl_stb => wb_ctrl_stb,
|
|
||||||
wb_ctrl_ack => wb_ctrl_ack,
|
|
||||||
wb_ctrl_we => wb_ctrl_we,
|
|
||||||
wb_ctrl_cti => "000",
|
|
||||||
wb_ctrl_bte => "00",
|
|
||||||
wb_ctrl_err => open,
|
|
||||||
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 @@
|
|||||||
|
none
|
@ -0,0 +1,72 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use std.textio.all;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.wishbone_types.all;
|
||||||
|
|
||||||
|
entity dram_init_mem is
|
||||||
|
port (
|
||||||
|
clk : in std_ulogic;
|
||||||
|
wb_in : in wb_io_master_out;
|
||||||
|
wb_out : out wb_io_slave_out
|
||||||
|
);
|
||||||
|
end entity dram_init_mem;
|
||||||
|
|
||||||
|
architecture rtl of dram_init_mem is
|
||||||
|
|
||||||
|
constant INIT_RAM_SIZE : integer := 16384;
|
||||||
|
constant INIT_RAM_ABITS :integer := 14;
|
||||||
|
constant INIT_RAM_FILE : string := "litedram/generated/sim/litedram_core.init";
|
||||||
|
|
||||||
|
type ram_t is array(0 to (INIT_RAM_SIZE / 4) - 1) of std_logic_vector(31 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*2) := temp_word(31 downto 0);
|
||||||
|
temp_ram(i*2+1) := temp_word(63 downto 32);
|
||||||
|
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
|
||||||
|
|
||||||
|
init_ram_0: process(clk)
|
||||||
|
variable adr : integer;
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
wb_out.ack <= '0';
|
||||||
|
if (wb_in.cyc and wb_in.stb) = '1' then
|
||||||
|
adr := to_integer((unsigned(wb_in.adr(INIT_RAM_ABITS-1 downto 2))));
|
||||||
|
if wb_in.we = '0' then
|
||||||
|
wb_out.dat <= init_ram(adr);
|
||||||
|
else
|
||||||
|
for i in 0 to 3 loop
|
||||||
|
if wb_in.sel(i) = '1' then
|
||||||
|
init_ram(adr)(((i + 1) * 8) - 1 downto i * 8) <=
|
||||||
|
wb_in.dat(((i + 1) * 8) - 1 downto i * 8);
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
wb_out.ack <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
wb_out.stall <= '0';
|
||||||
|
|
||||||
|
end architecture rtl;
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue