Commit cc8ba521 authored by Tristan Gingold's avatar Tristan Gingold

Rework plc urv memory map to improve speed.

TODO: add byte selects for data memory
parent bb956743
......@@ -34,8 +34,7 @@ use work.urv_pkg.all;
entity plc_urv is
generic(
g_IRAM_LOG_SIZE : natural := 10;
g_DRAM_LOG_SIZE : natural := 12);
g_IRAM_LOG_SIZE : natural := 10);
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
......@@ -61,16 +60,6 @@ architecture arch of plc_urv is
signal dm_data_select : std_logic_vector(3 downto 0);
signal dm_load, dm_store, dm_load_done, dm_store_done : std_logic;
signal reg_dm_addr, reg_dm_data_s : std_logic_vector(31 downto 0);
signal reg_dm_data_select : std_logic_vector(3 downto 0);
signal reg_dm_load, reg_dm_store : std_logic;
signal dm_cycle_in_progress, reg_dm_is_wishbone : std_logic;
signal dm_mem_rdata, dm_wb_rdata : std_logic_vector(31 downto 0);
signal dm_wb_write, dm_select_wb : std_logic;
signal reg_dm_data_write : std_logic;
signal dwb_out : t_wishbone_master_out;
begin
......@@ -111,18 +100,28 @@ begin
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
reg_dm_load <= '0';
reg_dm_store <= '0';
dwb_out.cyc <= '0';
dwb_out.stb <= '0';
else
reg_dm_load <= dm_load;
reg_dm_store <= dm_store;
reg_dm_addr <= dm_addr;
reg_dm_data_s <= dm_data_s;
reg_dm_data_select <= dm_data_select;
if dm_load = '1' or dm_store = '1' then
dwb_out.cyc <= '1';
dwb_out.stb <= '1';
dwb_out.adr <= dm_addr;
dwb_out.sel <= dm_data_select;
dwb_out.we <= dm_store;
dwb_out.dat <= dm_data_s;
elsif dwb_i.ack = '1' then
dwb_out.cyc <= '0';
dwb_out.stb <= '0';
end if;
end if;
end if;
end process;
dm_data_l <= dwb_i.dat;
dm_store_done <= dwb_i.ack and dwb_out.we;
dm_load_done <= dwb_i.ack and not dwb_out.we;
p_iram: process (clk_sys_i)
is
constant IRAM_WSIZE : natural := 2 ** (g_IRAM_LOG_SIZE - 2);
......@@ -143,106 +142,6 @@ begin
ram_wb_o.rty <= '0';
ram_wb_o.stall <= '0';
-- 1st MByte of the mem is the IRAM
reg_dm_is_wishbone <= '1' when reg_dm_addr(31 downto 20) /= x"000" else '0';
reg_dm_data_write <= not reg_dm_is_wishbone and reg_dm_store;
dm_data_l <= dm_wb_rdata when dm_select_wb = '1' else dm_mem_rdata;
p_ram: process (clk_sys_i)
is
variable mem : t_ram32_type (2**(g_DRAM_LOG_SIZE - 2) - 1 downto 0);
variable addr : natural range mem'range;
begin
if rising_edge(clk_sys_i) then
addr := to_integer(unsigned(reg_dm_addr(g_DRAM_LOG_SIZE - 1 downto 2)));
dm_mem_rdata <= mem(addr);
if reg_dm_data_write = '1' then
for i in 0 to 3 loop
if reg_dm_data_select (i) = '1' then
mem(addr)(8*i + 7 downto 8*i) := reg_dm_data_s(8*i + 7 downto 8*i);
end if;
end loop;
end if;
end if;
end process;
-- Wishbone bus arbitration / internal RAM access
p_wishbone_master : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
dwb_out.cyc <= '0';
dwb_out.stb <= '0';
dwb_out.adr <= (others => '0');
dwb_out.sel <= x"0";
dwb_out.we <= '0';
dwb_out.dat <= (others => '0');
dm_cycle_in_progress <= '0';
dm_load_done <= '0';
dm_store_done <= '0';
dm_select_wb <= '0';
else
if dm_cycle_in_progress = '0' then
if reg_dm_is_wishbone = '0' then
-- Internal access
if reg_dm_store = '1' then
dm_load_done <= '0';
dm_store_done <= '1';
dm_select_wb <= '0';
elsif reg_dm_load = '1' then
dm_load_done <= '1';
dm_store_done <= '0';
dm_select_wb <= '0';
else
dm_store_done <= '0';
dm_load_done <= '0';
dm_select_wb <= '0';
end if;
else
-- Wishbone access
if reg_dm_load = '1' or reg_dm_store = '1' then
dwb_out.cyc <= '1';
dwb_out.stb <= '1';
dwb_out.we <= reg_dm_store;
dm_wb_write <= reg_dm_store;
dwb_out.adr <= reg_dm_addr;
dwb_out.dat <= reg_dm_data_s;
dwb_out.sel <= reg_dm_data_select;
dm_load_done <= '0';
dm_store_done <= '0';
dm_cycle_in_progress <= '1';
else
dm_store_done <= '0';
dm_load_done <= '0';
dm_cycle_in_progress <= '0';
end if;
end if;
else
-- Wishbone transfer in progress.
if dwb_i.stall = '0' then
dwb_out.stb <= '0';
end if;
if dwb_i.ack = '1' then
if dm_wb_write = '0' then
dm_wb_rdata <= dwb_i.dat;
dm_select_wb <= '1';
dm_load_done <= '1';
else
dm_store_done <= '1';
dm_select_wb <= '0';
end if;
dm_cycle_in_progress <= '0';
dwb_out.cyc <= '0';
end if;
end if;
end if;
end if;
end process p_wishbone_master;
cpu_rst <= not rst_n_i;
p_im_valid : process(clk_sys_i)
......
......@@ -5,6 +5,16 @@ memory-map:
x-hdl:
busgroup: True
children:
- memory:
name: sram
address: 0x10000
interface: sram
memsize: 8k
children:
- reg:
name: value
access: rw
width: 32
- submap:
name: mailboxes
filename: "mbox_regs.cheby"
......
This diff is collapsed.
......@@ -134,21 +134,24 @@ begin
x"14", x"00", x"10", x"00",
others => x"00"),
-- Second command: load plc
1 => (x"10", x"2f", x"00", x"00",
x"00", x"20", x"10", x"00",
x"93", x"01", x"00", x"03",
1 => (x"10", x"2f", x"00", x"00", -- Load block
x"00", x"20", x"10", x"00", -- In plc RAM
x"93", x"01", x"00", x"04", -- plc_demo code
x"17", x"01", x"01", x"00",
x"13", x"01", x"c1", x"3f",
x"ef", x"00", x"c0", x"00",
x"ef", x"00", x"c0", x"01",
x"ef", x"00", x"40", x"01",
x"6f", x"f0", x"df", x"ff",
x"b7", x"57", x"34", x"12",
x"37", x"07", x"10", x"00",
x"93", x"87", x"87", x"67",
x"23", x"20", x"f7", x"00",
x"67", x"80", x"00", x"00",
x"b7", x"07", x"10", x"00",
x"23", x"a8", x"07", x"04",
x"67", x"80", x"00", x"00",
others => x"00"),
x"37", x"07", x"10", x"00",
x"83", x"27", x"07", x"03",
x"93", x"f7", x"17", x"00",
x"b3", x"07", x"f0", x"40",
x"93", x"f7", x"e7", x"ff",
x"23", x"28", x"f7", x"04",
x"6f", x"f0", x"df", x"fe"),
-- Third command: deassert plc reset
2 => (x"01", x"4b", x"00", x"00",
x"00", x"00", x"10", x"00",
......
......@@ -31,6 +31,7 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.genram_pkg.all;
library proasic3e;
use proasic3e.all;
......@@ -156,6 +157,11 @@ architecture rtl of diot_urv_top is
signal wb_plc_in : t_wishbone_slave_in;
signal wb_plc_out : t_wishbone_slave_out;
signal plc_sram_addr : std_logic_vector(12 downto 2);
signal plc_sram_dato : std_logic_vector(31 downto 0);
signal plc_sram_dati : std_logic_vector(31 downto 0);
signal plc_sram_wr : std_logic;
-- MEM bus for FIP cpu to write into PLC memory.
signal wb_mem_in : t_wishbone_slave_in;
signal wb_mem_out : t_wishbone_slave_out;
......@@ -388,19 +394,25 @@ begin
cyc_o <= '0';
stb_o <= '0';
we_o <= '0';
fip_ack <= '0';
else
cyc_o <= fip_cyc;
stb_o <= fip_stb;
we_o <= fip_we;
dat_o <= fip_dato;
adr_o <= fip_adr;
fip_ack <= ack_i;
fip_dati <= dat_i;
end if;
end if;
end process;
inst_fip_ack: entity work.gc_sync
port map (
clk_i => clk_2,
rst_n_a_i => rst_n,
d_i => ack_i,
q_o => fip_ack
);
wclk_o <= clk_2;
rst_o <= not rst_n;
......@@ -417,8 +429,7 @@ begin
inst_plc_urv: entity work.plc_urv
generic map (
g_iram_log_size => 10,
g_dram_log_size => 12
g_iram_log_size => 10
)
port map (
clk_sys_i => clk,
......@@ -435,6 +446,10 @@ begin
clk_i => clk,
wb_i => wb_plc_in,
wb_o => wb_plc_out,
sram_addr_o => plc_sram_addr,
sram_data_i => plc_sram_dati,
sram_data_o => plc_sram_dato,
sram_wr_o => plc_sram_wr,
mailboxes_mboxout_o => mbox_in_dat,
mailboxes_mboxout_wr_o => mbox_in_wr,
mailboxes_mboxin_i => mbox_out_reg,
......@@ -466,30 +481,112 @@ begin
relays_pins_6_o => open,
relays_pins_7_o => open
);
p_ram: process (clk)
is
constant c_DRAM_LOG_SIZE : natural := 12;
variable mem : t_ram32_type (2**(c_DRAM_LOG_SIZE - 2) - 1 downto 0);
variable addr : natural range mem'range;
begin
if rising_edge(clk) then
addr := to_integer(unsigned(plc_sram_addr(c_DRAM_LOG_SIZE - 1 downto 2)));
plc_sram_dati <= mem(addr);
if plc_sram_wr = '1' then
for i in 0 to 3 loop
if true then -- if reg_dm_data_select (i) = '1' then
mem(addr)(8*i + 7 downto 8*i) := plc_sram_dato(8*i + 7 downto 8*i);
end if;
end loop;
end if;
end if;
end process;
-------------------------------------------------------------------------------
GEN_REAL_IO: block
begin
-- slots assignment
slots_loops(0)(15 downto 0) <= s1_p_b(15 downto 0);
slots_loops(1)(13 downto 0) <= s2_p_b(13 downto 0);
slots_loops(2)(13 downto 0) <= s3_p_b(13 downto 0);
slots_loops(3)(8 downto 0) <= s4_p_b(13 downto 6) & s4_p_b(3);
slots_loops(4)(13 downto 0) <= s5_p_b(13 downto 0);
slots_loops(5)(15 downto 0) <= s7_p_b(15 downto 0);
gen_slots_0: for i in 15 downto 0 generate
inst_sync: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s1_p_b(i),
q_o => slots_loops(0)(i)
);
end generate;
slots_loops(0)(31 downto 16) <= (others=>'0');
gen_slots_1: for i in 13 downto 0 generate
inst_sync: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s2_p_b(i),
q_o => slots_loops(1)(i)
);
end generate;
slots_loops(1)(31 downto 14) <= (others=>'0');
gen_slots_2: for i in 13 downto 0 generate
inst_sync: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s3_p_b(i),
q_o => slots_loops(2)(i)
);
end generate;
slots_loops(2)(31 downto 14) <= (others=>'0');
gen_slots_3: for i in 13 downto 6 generate
inst_sync: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s4_p_b(i),
q_o => slots_loops(3)(i)
);
end generate;
inst_slots_3_3: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s4_p_b(3),
q_o => slots_loops(3)(3)
);
slots_loops(3)(31 downto 14) <= (others=>'0');
slots_loops(3)(5 downto 4) <= (others=>'0');
slots_loops(3)(2 downto 0) <= (others=>'0');
gen_slots_4: for i in 13 downto 0 generate
inst_sync: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s5_p_b(i),
q_o => slots_loops(4)(i)
);
end generate;
slots_loops(4)(31 downto 14) <= (others=>'0');
gen_slots_5: for i in 15 downto 0 generate
inst_sync: entity work.gc_sync
port map (
clk_i => clk,
rst_n_a_i => rst_n,
d_i => s7_p_b(i),
q_o => slots_loops(5)(i)
);
end generate;
slots_loops(5)(31 downto 16) <= (others=>'0');
s1_n_b(15 downto 0) <= slots_relays(0)(15 downto 0);
s2_n_b(13 downto 0) <= slots_relays(1)(13 downto 0);
s3_n_b(13 downto 0) <= slots_relays(2)(13 downto 0);
s4_n_b(13 downto 6) <= slots_relays(3)(8 downto 1);
s4_n_b(3) <= slots_relays(3)(0);
s4_n_b(13 downto 6) <= slots_relays(3)(13 downto 6);
s4_n_b(3) <= slots_relays(3)(3);
s5_n_b(13 downto 0) <= slots_relays(4)(13 downto 0);
s7_n_b(15 downto 0) <= slots_relays(5)(15 downto 0);
-- not used loops
slots_loops(0)(31 downto 16) <= (others=>'0');
slots_loops(1)(31 downto 14) <= (others=>'0');
slots_loops(2)(31 downto 14) <= (others=>'0');
slots_loops(3)(31 downto 9) <= (others=>'0');
slots_loops(4)(31 downto 14) <= (others=>'0');
end block;
-- Leds: assign to '0' to switch on the led, 'Z' to switch off.
......
......@@ -9,7 +9,7 @@ SIZE = $(CROSS_COMPILE)size
PROG=plc_mbox
CFLAGS = -mabi=ilp32 -march=rv32im -Os -Wall
CFLAGS = -mabi=ilp32 -march=rv32im -Os -Wall -ffreestanding -fno-delete-null-pointer-checks
OBJS = crt0.o $(PROG).o
LDS = plc.ld
......
......@@ -8,7 +8,7 @@ MEMORY
LENGTH = 1024
bss :
ORIGIN = 0x00010000,
LENGTH = 2048
LENGTH = 4096
/* Sorry, but there is no initialized ram. */
empty :
......
......@@ -7,7 +7,7 @@ void
init (void)
{
volatile struct plc_urv_regs *regs =
(volatile struct plc_urv_regs *)0x100000;
(volatile struct plc_urv_regs *)0x00000;
regs->relays.SLOT = 0;
}
......@@ -16,9 +16,11 @@ void
main (void)
{
volatile struct plc_urv_regs *regs =
(volatile struct plc_urv_regs *)0x100000;
(volatile struct plc_urv_regs *)0x00000;
while (1) {
unsigned v = regs->loops.SLOT;
regs->relays.SLOT = -(v & 1) & (~1);
}
}
......@@ -2,87 +2,103 @@
#define __CHEBY__PLC_URV_REGS__H__
#include "mbox_regs.h"
#define PLC_URV_REGS_SIZE 96
#define PLC_URV_REGS_SIZE 73824
/* None */
#define PLC_URV_REGS_MAILBOXES 0x0UL
#define PLC_URV_REGS_SRAM 0x10000UL
#define PLC_URV_REGS_SRAM_SIZE 4
/* None */
#define PLC_URV_REGS_SRAM_VALUE 0x0UL
/* None */
#define PLC_URV_REGS_MAILBOXES 0x12000UL
#define PLC_URV_REGS_MAILBOXES_SIZE 16
/* presence lines for boards */
#define PLC_URV_REGS_PRESENCE 0x10UL
#define PLC_URV_REGS_PRESENCE 0x12010UL
#define PLC_URV_REGS_PRESENCE_EN_MASK 0xffUL
#define PLC_URV_REGS_PRESENCE_EN_SHIFT 0
/* None */
#define PLC_URV_REGS_LOOPS 0x20UL
#define PLC_URV_REGS_LOOPS 0x12020UL
#define PLC_URV_REGS_LOOPS_SIZE 32
/* None */
#define PLC_URV_REGS_LOOPS_PINS_0 0x20UL
#define PLC_URV_REGS_LOOPS_PINS_0 0x12020UL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_1 0x24UL
#define PLC_URV_REGS_LOOPS_PINS_1 0x12024UL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_2 0x28UL
#define PLC_URV_REGS_LOOPS_PINS_2 0x12028UL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_3 0x2cUL
#define PLC_URV_REGS_LOOPS_PINS_3 0x1202cUL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_4 0x30UL
#define PLC_URV_REGS_LOOPS_PINS_4 0x12030UL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_5 0x34UL
#define PLC_URV_REGS_LOOPS_PINS_5 0x12034UL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_6 0x38UL
#define PLC_URV_REGS_LOOPS_PINS_6 0x12038UL
/* None */
#define PLC_URV_REGS_LOOPS_PINS_7 0x3cUL
#define PLC_URV_REGS_LOOPS_PINS_7 0x1203cUL
/* None */
#define PLC_URV_REGS_RELAYS 0x40UL
#define PLC_URV_REGS_RELAYS 0x12040UL
#define PLC_URV_REGS_RELAYS_SIZE 32
/* None */
#define PLC_URV_REGS_RELAYS_PINS_0 0x40UL
#define PLC_URV_REGS_RELAYS_PINS_0 0x12040UL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_1 0x44UL
#define PLC_URV_REGS_RELAYS_PINS_1 0x12044UL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_2 0x48UL
#define PLC_URV_REGS_RELAYS_PINS_2 0x12048UL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_3 0x4cUL
#define PLC_URV_REGS_RELAYS_PINS_3 0x1204cUL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_4 0x50UL
#define PLC_URV_REGS_RELAYS_PINS_4 0x12050UL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_5 0x54UL
#define PLC_URV_REGS_RELAYS_PINS_5 0x12054UL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_6 0x58UL
#define PLC_URV_REGS_RELAYS_PINS_6 0x12058UL
/* None */
#define PLC_URV_REGS_RELAYS_PINS_7 0x5cUL
#define PLC_URV_REGS_RELAYS_PINS_7 0x1205cUL
struct plc_urv_regs {
/* [0x0]: SUBMAP (no description) */
/* padding to: 16384 words */
uint32_t __padding_0[16384];
/* [0x10000]: MEMORY (no description) */
struct sram {
/* [0x0]: REG (rw) (no description) */
uint32_t value;
} sram[2048];
/* [0x12000]: SUBMAP (no description) */
struct mbox_regs mailboxes;
/* padding to: 4 words */
uint32_t __padding_0[1];
/* padding to: 18436 words */
uint32_t __padding_1[1];
/* [0x10]: REG (ro) presence lines for boards */
/* [0x12010]: REG (ro) presence lines for boards */
uint32_t presence;
/* padding to: 8 words */
uint32_t __padding_1[3];
/* padding to: 18440 words */
uint32_t __padding_2[3];
/* [0x20]: BLOCK (no description) */
/* [0x12020]: BLOCK (no description) */
struct loops {
/* [0x0]: REG (ro) (no description) */
uint32_t pins_0;
......@@ -109,7 +125,7 @@ struct plc_urv_regs {
uint32_t pins_7;
} loops;
/* [0x40]: BLOCK (no description) */
/* [0x12040]: BLOCK (no description) */
struct relays {
/* [0x0]: REG (rw) (no description) */
uint32_t pins_0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment