Commit 879b5725 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

a

parent 7cc2ac4a
......@@ -29,6 +29,47 @@ function vi(name, h, l)
return s;
end
-- instance of a component
function vinstance(name, component, maps)
local s={};
s.t="instance";
s.name=name;
s.component = component;
s.maps = maps;
return s;
end
-- port map
function vpm(to, from)
local s={};
s.t="portmap";
s.to = to;
s.from = from;
return s;
end
-- generic map
function vgm(to, from)
local s={};
s.t="genmap";
s.to = to;
s.from = from;
return s;
end
-- combinatorial process: process(sensitivity_list) begin {code} end process;
function vsyncprocess(slist, code)
local s={};
s.t="combprocess";
s.slist = slist;
s.code=code;
return s;
end
-- synchronous process: process(clk, rst) begin {code} end process;
function vsyncprocess(clk, rst, code)
local s={};
......@@ -39,6 +80,8 @@ function vsyncprocess(clk, rst, code)
return s;
end
-- reset in process
function vreset(level, code)
local s={};
......@@ -148,30 +191,16 @@ function port(type, nbits, dir, name, comment)
return t;
end
global_ports = {};
global_signals = {};
function cgen_build_wishbone_ports()
local ports = {
port(BIT, 0, "in", "rst_n_i"),
port(BIT, 0, "in", "wb_clk_i"),
};
if(address_bus_width > 0 ) then
table_join(ports, { port(SLV, address_bus_width, "in", "wb_addr_i") });
end
table_join(ports, {
port(SLV, DATA_BUS_WIDTH, "in", "wb_data_i"),
port(SLV, DATA_BUS_WIDTH, "out", "wb_data_o"),
port(BIT, 0, "in", "wb_cyc_i"),
port(BIT, 0, "in", "wb_sel_i"),
port(BIT, 0, "in", "wb_stb_i"),
port(BIT, 0, "in", "wb_we_i"),
port(BIT, 0, "out", "wb_ack_o")
});
return ports;
function add_global_signals(s)
table_join(global_signals, s);
end
function add_global_ports(p)
table_join(global_ports, p);
end
function cgen_build_clock_list()
local allclocks = tree_2_table("clock");
......@@ -194,16 +223,7 @@ function cgen_build_siglist()
siglist = tree_2_table("signals");
wb_sigs = { signal(BIT, 0, "wb_ack_regbank"),
signal(UNSIGNED, 4, "ack_cntr"),
signal(BIT,0, "ack_in_progress"),
signal(BIT,0, "tmpbit"),
signal(SLV, DATA_BUS_WIDTH, "rddata_reg"),
signal(SLV, DATA_BUS_WIDTH, "wrdata_reg"),
signal(SLV, address_bus_width, "rwaddr_reg")
};
table_join(siglist, wb_sigs);
table_join(siglist, global_signals);
return siglist;
end
......@@ -212,7 +232,7 @@ end
function cgen_build_portlist()
local portlist = {};
table_join(portlist, cgen_build_wishbone_ports());
table_join(portlist, global_ports);
table_join(portlist, cgen_build_clock_list());
table_join(portlist, tree_2_table("ports"));
return portlist;
......
This diff is collapsed.
library ieee;
use ieee.std_logic_1164.all;
library altera_mf;
use altera_mf.all;
library wbgen2;
use wbgen2.all;
entity wbgen2_dpssram is
generic (
g_data_width : natural;
g_size : natural;
g_addr_width : natural;
g_dual_clock : boolean := false;
g_use_bwsel : boolean := false);
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic
);
end wbgen2_dpssram;
architecture syn of wbgen2_dpssram is
component altsyncram
generic (
address_reg_b : string;
byteena_reg_b : string;
byte_size : natural;
clock_enable_input_a : string;
clock_enable_input_b : string;
clock_enable_output_a : string;
clock_enable_output_b : string;
indata_reg_b : string;
intended_device_family : string;
lpm_type : string;
numwords_a : natural;
numwords_b : natural;
operation_mode : string;
outdata_aclr_a : string;
outdata_aclr_b : string;
outdata_reg_a : string;
outdata_reg_b : string;
power_up_uninitialized : string;
read_during_write_mode_port_a : string;
read_during_write_mode_port_b : string;
widthad_a : natural;
widthad_b : natural;
width_a : natural;
width_b : natural;
width_byteena_a : natural;
width_byteena_b : natural;
wrcontrol_wraddress_reg_b : string);
port (
wren_a : in std_logic;
clock0 : in std_logic;
wren_b : in std_logic;
clock1 : in std_logic;
byteena_a : in std_logic_vector (3 downto 0);
byteena_b : in std_logic_vector (3 downto 0);
address_a : in std_logic_vector (4 downto 0);
address_b : in std_logic_vector (4 downto 0);
rden_a : in std_logic;
q_a : out std_logic_vector (31 downto 0);
rden_b : in std_logic;
q_b : out std_logic_vector (31 downto 0);
data_a : in std_logic_vector (31 downto 0);
data_b : in std_logic_vector (31 downto 0));
end component;
signal clksel : string(1 to 6);
signal bwsel_int_a : std_logic_vector((g_data_width+7)/8 downto 0);
signal bwsel_int_b : std_logic_vector((g_data_width+7)/8 downto 0);
begin -- syn
-- genclksel1: if(g_dual_clock = true) generate
-- clksel <= "CLOCK1";
-- end generate genclksel1;
-- genclksel2: if(g_dual_clock = false) generate
-- clksel <= "CLOCK0";
-- end generate genclksel2;
clksel <= "CLOCK1" when g_dual_clock = true else "CLOCK0";
genbwsel1: if(g_use_bwsel = true) generate
bwsel_int_a <= bwsel_a_i;
bwsel_int_b <= bwsel_b_i;
end generate genbwsel1;
genbwsel2: if(g_use_bwsel = false) generate
bwsel_int_a <= (others => '1');
bwsel_int_b <= (others => '1');
end generate genbwsel2;
altsyncram_component : altsyncram
generic map (
address_reg_b => clksel,
byteena_reg_b => clksel,
byte_size => 8,
clock_enable_input_a => "BYPASS",
clock_enable_input_b => "BYPASS",
clock_enable_output_a => "BYPASS",
clock_enable_output_b => "BYPASS",
indata_reg_b => clksel,
intended_device_family => "Cyclone III",
lpm_type => "altsyncram",
numwords_a => g_size,
numwords_b => g_size,
operation_mode => "BIDIR_DUAL_PORT",
outdata_aclr_a => "NONE",
outdata_aclr_b => "NONE",
outdata_reg_a => "UNREGISTERED",
outdata_reg_b => "UNREGISTERED",
power_up_uninitialized => "FALSE",
read_during_write_mode_port_a => "OLD_DATA",
read_during_write_mode_port_b => "OLD_DATA",
widthad_a => g_addr_width,
widthad_b => g_addr_width,
width_a => g_data_width,
width_b => g_data_width,
width_byteena_a => (g_data_width+7)/8,
width_byteena_b => (g_data_width+7)/8,
wrcontrol_wraddress_reg_b => clksel
)
port map (
wren_a => wr_a_i,
clock0 => clk_a_i,
wren_b => wr_b_i,
clock1 => clk_b_i,
byteena_a => bwsel_int_a,
byteena_b => bwsel_int_b,
address_a => addr_a_i,
address_b => addr_b_i,
rden_a => rd_a_i,
rden_b => rd_b_i,
data_a => data_a_i,
data_b => data_b_i,
q_a => data_a_o,
q_b => data_b_o
);
end syn;
library ieee;
use ieee.std_logic_1164.all;
library wbgen2;
package wbgen2_pkg is
component wbgen2_dpssram
generic (
g_data_width : natural;
g_size : natural;
g_addr_width : natural;
g_dual_clock : boolean;
g_use_bwsel : boolean);
port (
clk_a_i : in std_logic_vector((g_data_width+7)/8 downto 0);
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : in std_logic_vector(g_data_width-1 downto 0);
data_b_o : in std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic);
end component;
end wbgen2_pkg;
-- here comes our peripheral definition
peripheral {
-- short (human-readable) name for the peripheral.
name = "GPIO Port";
-- a longer description, if you want
description = "A sample 32-bit general-purpose bidirectional I/O port, explaining how to use SLV and PASS-THROUGH registers.";
-- name of the target VHDL entity to be generated
hdl_entity = "wb_slave_gpio_port";
-- prefix for all the generated ports belonging to our peripheral
prefix = "gpio";
-- Pin direction register. Readable and writable from the bus, readable from the device.
reg {
name = "Pin direction register";
description = "A register defining the direction of the GPIO potr pins.";
prefix = "ddr";
-- a single, anonymous field (no prefix) of type SLV.
field {
name = "Pin directions";
description = "Each bit in this register defines the direction of corresponding pin of the GPIO port. 1 means the pin is an OUTPUT, 0 means the pin is an INPUT";
-- there is (deliberately) no prefix defined for this field. Since we have only one field in the register "ddr", we can omit the prefix - wbgen2 will produce signal names
-- containing only prefixes of the peripheral and the parent register.
-- type of our field - std_logic_vector
type = SLV;
-- size - we want 32-bits wide port :)
size = 32;
-- the field will be readable/writable from the Wishbone bus
access_bus = READ_WRITE;
-- .. and readable from the peripheral
access_dev = READ_ONLY;
};
};
-- Pin input state register. Readable the bus, writable from the device.
reg {
name = "Pin input state register";
description = "A register containing the current state of input pins.";
prefix = "psr";
-- a single, anonymous field (no prefix) of type SLV.
field {
name = "Pin input state";
description = "Each bit in this register reflects the state of corresponding GPIO port pin.";
-- no prefix here as well (see above)
-- type of our field - std_logic_vector
type = SLV;
-- size - we want 32-bits wide port :)
size = 32;
-- the field will be readable from the Wishbone bus
access_bus = READ_ONLY;
-- .. and writable from the peripheral
access_dev = WRITE_ONLY;
};
};
-- Port output register. Shows how to use PASS-THROUGH regs
reg {
name = "Port output register";
description = "Register containing the output pin state.";
prefix = "pdr";
-- a single, anonymous field (no prefix) of type PASS-THROUGH.
field {
name = "Port output value";
-- the description isn't really necessary here :)
-- description = "Writing '1' sets the corresponding GPIO pin to '1'";
-- type of our field - PASS_THROUGH. In this mode, the slave core is not storing the register value. Instead it provides the raw value
-- (taken from the wishbone data input) and a strobe signal, asserted for single clock cycle upon write operation to the register.
-- The wishbone data input will be fed directly to gpio_pdr_o and each write operation to this register will generate a single-cycle positive
-- pulse on gpio_pdr_wr_o signal.
type = PASS_THROUGH;
size = 32;
-- access flags don't apply for the PASS-THROUGH regsiters, so we can omit them.
};
};
-- Set output register. Shows how to use PASS-THROUGH regs
reg {
name = "Set output pin register";
description = "Writing '1' sets the corresponding GPIO pin to '1'";
prefix = "sopr";
-- Our driver developer would want these two (SOPR and COPR) registers' addresses to be aligned to multiple of 4 :)
align = 4;
field {
name = "Set output pin register";
type = PASS_THROUGH;
size = 32;
};
};
-- Clear output register. Designed identically as the previous reg.
reg {
name = "Clear output pin register";
description = "Writing '1' clears the corresponding GPIO pin";
prefix = "copr";
field {
name = "Clear output pin register";
type = PASS_THROUGH;
size = 32;
};
};
ram {
name = "memory 1";
prefix = "mem1";
size = 256;
width = 32;
byte_select = true;
clock = "clk1_i";
access_bus = READ_WRITE;
access_dev = READ_WRITE;
};
ram {
name = "memory 2";
prefix = "mem2";
size = 512;
width = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
-- irq {
-- prefix
-- name
-- desc
-- active
-- prio
-- };
};
This diff is collapsed.
......@@ -2,15 +2,14 @@
wbgen2_version="0.3"
wbgen2_libdir="."
wbgen2_libdir="/home/slayer/wbgen2_svn/wbgen2"
device_family="altera_cyclone3";
options = {};
options.reset_type = "asynchronous";
options.target_interconnect = "wishbone";
options.target_interconnect = "wb-classic";
options.register_data_output = false;
dofile(wbgen2_libdir.."/wbgen_common.lua");
dofile(wbgen2_libdir.."/cgen_common.lua");
......@@ -18,6 +17,7 @@ dofile(wbgen2_libdir.."/cgen_vhdl.lua");
dofile(wbgen2_libdir.."/cgen_verilog.lua");
dofile(wbgen2_libdir.."/wbgen_regbank.lua");
dofile(wbgen2_libdir.."/wbgen_rams.lua");
dofile(wbgen2_libdir.."/target_wishbone.lua");
function chk_nil(p,s)
if(p == nil) then
......@@ -98,14 +98,10 @@ foreach_field(calc_size);
foreach_reg(check_max_size);
foreach_field(calc_field_offsets);
--foreach_field(function(reg, field) print
foreach_reg(calc_address_sizes);
assign_addresses();
--foreach_reg(gen_vhdl_signals);
--foreach_reg(gen_vhdl_constants);
tree=gen_hdl_regbank();
tree=gen_bus_logic_wishbone();
cgen_build_signals_ports();
cgen_generate_hdl_init(options.output_hdl_file)
......
#!/usr/bin/lua
function gen_vhdl_ramcode(ram)
function gen_code_ram(ram)
local prefix = string.lower(periph.hdl_prefix.."_"..ram.hdl_prefix);
local maps = {};
print("GENRAMCODE!"..ram.name);
-- generate the RAM-related ports
ram.full_prefix = prefix;
ram.signals = {};
ram.ports = { port (SLV, ram.addr_bits - ram.wrap_bits, "in", prefix.."_addr_i", "Ports for RAM: "..ram.name ) };
ram.reset_code_main = {};
table_join(maps, { vpm ("clk_a_i", "bus_clock");
vpm ("clk_b_i", csel(ram.clock ~= nil, ram.clock, "bus_clock"));
vpm ("addr_b_i", prefix.."_addr_i"); });
if(match(ram.access_dev, {READ_ONLY, READ_WRITE})) then
table_join(ram.ports, { port(SLV, ram.width, "out", prefix.."_data_o") });
table_join(ram.ports, { port(SLV, ram.width, "out", prefix.."_data_o", "Read data output"),
port(BIT, 0, "in", prefix.."_rd_i", "Read strobe input (active high)") });
table_join(maps, { vpm ("data_b_o", prefix.."_data_o");
vpm ("rd_b_i", prefix.."_rd_i"); } );
end
if(match(ram.access_dev, {WRITE_ONLY, READ_WRITE})) then
table_join(ram.ports, { port(SLV, ram.width, "in", prefix.."_data_i"),
port(BIT, 0, "in", prefix.."_we_i") });
table_join(ram.ports, { port(SLV, ram.width, "in", prefix.."_data_i", "Write data input"),
port(BIT, 0, "in", prefix.."_wr_i", "Write strobe (active high)") });
table_join(maps, { vpm ("data_b_i", prefix.."_data_i");
vpm ("wr_b_i", prefix.."_wr_i"); });
if(ram.byte_select == true and ram.width >= 16) then
table_join(ram.ports, { port (SLV, ram.width/8, "in", prefix.."_bwsel_i", "Byte select input (active high)") } );
table_join(maps, { vpm ("bwsel_b_i", prefix.."_bwsel_i"); } );
end
end
local raminst = vhdl_new_instance();
table_join(maps, { vpm ("addr_a_i", vi("rwaddr_reg", log2up(ram.size)-1, 0)) });
end
if(match(ram.access_bus, {READ_ONLY, READ_WRITE})) then
table_join(ram.signals, { signal(SLV, ram.width, prefix.."_rddata_int"),
signal(BIT, 0, prefix.."_rd_int") } );
table_join(maps, { vpm ("data_a_o", vi(prefix.."_rddata_int", ram.width-1, 0));
vpm ("rd_a_i", prefix.."_rd_int"); } );
table_join(ram.reset_code_main, { va(prefix.."_rd_int", 0); });
end
if(match(ram.access_bus, {WRITE_ONLY, READ_WRITE})) then
table_join(ram.signals, { signal(BIT, 0, prefix.."_wr_int") } );
function gen_vhdl_rams()
foreach_reg(function(reg) if(reg.__type == TYPE_RAM) then gen_vhdl_ramcode(reg); end end);
end
\ No newline at end of file
table_join(maps, { vpm ("data_a_i", vi("wrdata_reg", ram.width-1, 0));
vpm ("wr_a_i", prefix.."_wr_int"); });
table_join(ram.reset_code_main, { va(prefix.."_wr_int", 0); });
if(ram.byte_select == true and ram.width >= 16) then
table_join(maps, { vpm ("bwsel_a_i", vi("bwsel_reg", math.floor(ram.width/8)-1, 0)); } );
end
end
-- fill in all the generic mappings
table_join(maps, { vgm ("g_data_width", ram.width);
vgm ("g_size", ram.size);
vgm ("g_addr_width", log2up(ram.size));
vgm ("g_dual_clock", csel(ram.clock ~= nil, "true", "false"));
vgm ("g_use_bwsel", csel(ram.byte_select == true, "true", "false"));
});
ram.extra_code = { vcomment ("RAM block instantiation for memory: "..ram.name);
vinstance (prefix.."_raminst", "wbgen2_dpssram", maps ); };
end
......@@ -576,7 +576,7 @@ function gen_hdl_code_passthrough(field, reg)
field.write_code = { va(prefix.."_wr_o", 1); };
field.ackgen_code_pre = { va(prefix.."_wr_o", 0); };
field.ackgen_code = { va(prefix.."_wr_o", 0); };
field.extra_code = { vcomment("-- pass-through field: "..field.name.." in register: "..reg.name);
field.extra_code = { vcomment("pass-through field: "..field.name.." in register: "..reg.name);
va(prefix.."_o", vir("wrdata_reg", field)); }
else
......@@ -637,167 +637,16 @@ function gen_hdl_code_reg_field(field, reg)
end
-- generates VHDL for single register
function gen_hdl_code_reg(reg)
foreach_subfield(reg, function(field, reg) gen_hdl_code_reg_field(field, reg); end );
function gen_abstract_code(reg)
if(reg.__type == TYPE_RAM) then
gen_code_ram(reg);
else
foreach_subfield(reg, function(field, reg) gen_hdl_code_reg_field(field, reg); end );
end
end
function gen_hdl_block_select_bits()
return vi("rwaddr_reg", address_bus_width-1, (address_bus_width - address_bus_select_bits));
end
-- generates the entire VHDL register-bank access stuff
function gen_hdl_regbank()
local s;
local ramcount = 0;
-- vhdl_new_code();
foreach_reg(function(reg)
if(reg.__type == TYPE_REG) then
gen_hdl_code_reg(reg);
end
end );
-- vhdl ("");
local resetcode={};
local ackgencode={};
local preackcode={};
foreach_field(function(field, reg)
-- print("rstcode: ", field.reset_code_main);
table_join(resetcode, field.reset_code_main);
end );
foreach_reg(function(reg)
if(reg.__type == TYPE_REG) then
foreach_subfield(reg, function(field, reg)
table_join(ackgencode, field.ackgen_code);
end );
end
end);
foreach_reg(function(reg)
if(reg.__type == TYPE_REG) then
foreach_subfield(reg, function(field, reg)
table_join(preackcode, field.ackgen_code_pre);
end );
end
end);
-- count the RAMs in the design
foreach_reg(function(reg)
if(reg.__type == TYPE_RAM) then
ramcount = ramcount + 1;
end
end
);
local fsmcode={};
foreach_reg(function(reg)
if(reg.__type == TYPE_REG) then
local acklen = find_max(reg, "acklen");
local rcode={};
local wcode={};
foreach_subfield(reg, function(field, reg) table_join(wcode, field.write_code); end );
foreach_subfield(reg, function(field, reg) table_join(rcode, field.read_code); end );
local rwcode = {
vif(vequal("wb_we_i" ,1), {
wcode
}, {
rcode
}); };
table_join(rwcode, { va("wb_ack_regbank", csel((acklen==1),1,0)); } );
table_join(rwcode, { va("ack_cntr", math.max(acklen-1, 0)); } );
table_join(rwcode, { va("ack_in_progress", 1); } );
if(regbank_address_bits > 0) then
rwcode = { vcase(reg.base, rwcode); };
end
table_join(fsmcode, rwcode);
end
end );
-- vhdl ("if ( wb_sel_i = '1' and wb_cyc_i = '1' and wb_stb_i = '1' ) then");
if(regbank_address_bits > 0) then
table_join(fsmcode, { vcasedefault({
va("ack_in_progress", 0);
va("ack_cntr", 0);
va("wb_ack_regbank", 0);
}); });
fsmcode = { vswitch(vi("rwaddr_reg", regbank_address_bits - 1, 0), fsmcode); };
end
fsmcode = { vif(vand(vequal("wb_cyc_i", 1), vequal("wb_stb_i", 1)), { fsmcode }, { va("wb_ack_regbank", 0) }); };
local code = {
vsyncprocess("wb_clk_i", "rst_n_i", {
vreset(0, {
va("wb_ack_regbank", 0);
va("ack_in_progress", 0);
va("ack_cntr", 0);
va("rddata_reg", 0);
resetcode
});
vposedge ({
vif(vequal("ack_in_progress",1), {
vif(vequal("ack_cntr", 0), {
ackgencode;
va("wb_ack_regbank", 0);
va("ack_in_progress", 0);
}, {
preackcode;
va("ack_cntr", vsub("ack_cntr", 1));
vif(vequal("ack_cntr", 1), {
va("wb_ack_regbank", 1);
} , {
va("wb_ack_regbank", 0);
});
});}, { -- else ack_in_progress = 0
fsmcode
});
});
});
va("wb_data_o", "rddata_reg");
va("wrdata_reg", "wb_data_i");
va("rwaddr_reg", "wb_addr_i");
};
-- vhdl_indent_right();
foreach_reg(function(reg)
if(reg.extra_code ~= nil) then
table_join(code, {vcomment("extra code for reg/fifo/mem: "..reg.name);});
table_join(code, reg.extra_code);
end
foreach_subfield(reg, function(field, reg) table_join(code, field.extra_code); end );
end);
return code;
end
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