Commit cc54a8c2 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

--no commit message

--no commit message
parent 879b5725
#!/usr/bin/lua
-- wbgen2, (c) 2010 Tomasz Wlostowski/CERN BE-Co-HT
-- LICENSED UNDER GPL v2
-- File: cgen_c_headers.lua
--
-- The C header code generator.
--
function cgen_c_field_define(field, reg)
local prefix=string.upper(periph.c_prefix).."_"..string.upper(reg.c_prefix).."_"..string.upper(field.c_prefix);
emit("");
emit("/* definitions for field: "..field.name.." in reg: "..reg.name.." */");
if(field.type == BIT or field.type == MONOSTABLE) then
emit("#define "..prefix.." (1<<"..field.offset..")");
else
print(field.offset, field.size);
emit("#define "..prefix.."_MASK "..string.format("0x%08x", (math.pow(2, field.size)-1) * math.pow(2, field.offset)));
emit("#define "..prefix.."_SHIFT "..string.format("%d", field.offset));
emit("#define "..prefix.."_W(value) "..string.format("(((value) & 0x%08x) << %d)", math.pow(2, field.size)-1, field.offset));
if(field.type == SIGNED) then
emit("#define "..prefix.."_R(reg) "..string.format("( ((reg)&0x%08x ? 0x%08x : 0) | (((reg) >> %d) & 0x%08x))",
math.pow(2, field.offset + field.size - 1), -- sign mask
(math.pow(2, 32-field.size)-1) * math.pow(2, field.size), -- sign extension mask
field.offset,
math.pow(2, field.size)-1));
else
emit("#define "..prefix.."_R(reg) "..string.format("(((reg) >> %d) & 0x%08x)", field.offset, math.pow(2, field.size)-1));
end
end
end
function cgen_c_ramdefs(ram)
local prefix = string.upper(periph.c_prefix).."_"..string.upper(ram.c_prefix);
emit("/* definitions for RAM: "..ram.name.." *);
emit(string.format("#define "..prefix.."_BYTES 0x%08x %-50s", ram.size * ram.width / 8, "/* size in bytes */"));
emit(string.format("#define "..prefix.."_WORDS 0x%08x %-50s", ram.size, "/* size in "..ram.width.."-bit words, 32-bit aligned */"));
end
function cgen_c_field_masks()
foreach_reg(function(reg)
if(reg.__type == TYPE_REG and reg.num_fields ~= nil and reg.num_fields > 0) then
emit("/* definitions for register: "..reg.name.." */);
foreach_subfield(reg, function(field, reg) cgen_c_field_define(field, reg) end);
elseif (reg.__type == TYPE_RAM) then
cgen_c_ramdefs(reg);
end
end);
end
function cgen_c_headers_reg(reg)
foreach_subfield(reg, function(field, reg)
emit()
end);
end
function cgen_c_headers_ram()
end
function cgen_c_fileheader()
emit ("/*");
emit (" Register definitions for slave core: "..periph.name);
emit ("");
emit (" * File : "..options.output_c_header_file);
emit (" * Author : auto-generated by wbgen2 from "..input_wb_file);
emit (" * Created : "..os.date());
emit (" * Standard : ANSI C");
emit ("");
emit (" THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE "..input_wb_file);
emit (" DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!");
emit ("");
emit ("*/");
end
function cgen_c_struct()
local cur_offset = 0;
local pad_id = 0;
function pad_struct(base)
if(cur_offset < base) then
emit("/* padding to: "..base.." words */");
emit("uint32_t __padding_"..pad_id.."["..(base - cur_offset).."];");
pad_id=pad_id+1;
cur_offset = base;
end
end
emit("PACKED struct "..string.upper(periph.c_prefix).."_WB {");
indent_right();
-- emit struct entires for REGs
foreach_reg(function(reg)
if(reg.__type == TYPE_REG) then
pad_struct(reg.base);
emit("/* "..reg.name.." */");
emit("volatile uint32_t "..string.upper(reg.prefix)..";");
cur_offset = cur_offset + 1;
end
end);
-- .. and for RAMs
foreach_reg(function(ram)
if(ram.__type == TYPE_RAM) then
local base = math.pow(2, ram.select_bits) *
math.pow (2, address_bus_width - address_bus_select_bits);
pad_struct(base);
emiti();
emitx("/* RAM: "..ram.name..", "..ram.size.." "..ram.width.."-bit words, "..DATA_BUS_WIDTH.."-bit aligned, "..csel(ram.byte_select, "byte", "word").."-addressable");
if(ram.wrap_bits > 0) then
emitx(", mirroring: "..math.pow(2, ram.wrap_bits).." times */\n");
else
emitx(" */\n");
end
if(ram.byte_select) then
emit("volatile uint8_t "..string.upper(ram.prefix).." ["..(ram.size * (DATA_BUS_WIDTH/8) * math.pow(2, ram.wrap_bits)) .."];");
else
emit("volatile uint32_t "..string.upper(ram.prefix).." ["..(ram.size * math.pow(2, ram.wrap_bits)) .."];");
end
end
end);
indent_left();
emit("};");
end
function cgen_generate_c_header_code()
cgen_new_snippet();
cgen_c_fileheader();
emit("");
emit("#ifndef __WBGEN2_REGDEFS_"..string.upper(string.gsub(input_wb_file,"%.","_")))
emit("#define __WBGEN2_REGDEFS_"..string.upper(string.gsub(input_wb_file,"%.","_")))
emit("");
emit("#include <inttypes.h>");
emit("");
emit("#if defined( __GNUC__)");
emit("#define PACKED __attribute__ ((packed))");
emit("#else");
emit("#error \"Unsupported compiler?\"");
emit("#endif");
emit("");
emit("#ifndef __WBGEN2_MACROS_DEFINED__");
emit("#define __WBGEN2_MACROS_DEFINED__");
emit("#define WBGEN2_GENMASK(offset, size) (((1<<(size))-1) << (offset))");
emit("#define WBGEN2_GENWRITE(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))");
emit("#endif");
cgen_c_field_masks();
emit("");
cgen_c_struct();
emit("");
emit("#endif");
cgen_write_current_snippet();
end
......@@ -60,7 +60,7 @@ function vgm(to, from)
end
-- combinatorial process: process(sensitivity_list) begin {code} end process;
function vsyncprocess(slist, code)
function vcombprocess(slist, code)
local s={};
s.t="combprocess";
s.slist = slist;
......@@ -168,7 +168,18 @@ function vsub(a,b)
return s;
end
function vothers(value)
local s={}
s.t="others";
s.val=value;
return s;
end
function vopenpin()
local s={}
s.t="openpin";
return s;
end
-- constructor for a HDL signal
function signal(type, nbits, name, comment)
......@@ -202,6 +213,7 @@ function add_global_ports(p)
table_join(global_ports, p);
end
function cgen_build_clock_list()
local allclocks = tree_2_table("clock");
local i,v;
......@@ -241,6 +253,9 @@ end
function cgen_find_sigport(name)
for i,v in pairs(g_portlist) do if(name == v.name) then return v; end end
for i,v in pairs(g_siglist) do if(name == v.name) then return v; end end
die("cgen internal error: undefined signal '"..name.."'");
return nil;
end
......@@ -289,18 +304,18 @@ function cgen_get_snippet()
end
function cgen_write_current_snippet()
hdl_file.write(hdl_file, emit_code);
output_code_file.write(output_code_file, emit_code);
end
function cgen_write_snippet(s)
hdl_file.write(hdl_file, s);
output_code_file.write(output_code_file, s);
end
function cgen_generate_hdl_init(filename)
hdl_file = io.open(filename, "w");
function cgen_generate_init(filename)
output_code_file = io.open(filename, "w");
end
function cgen_generate_hdl_done()
hdl_file.close(hdl_file);
function cgen_generate_done()
output_code_file.close(output_code_file);
end
......@@ -56,7 +56,7 @@ function cgen_vhdl_header()
-- do we have RAMs or FIFOs? - if yes, include the wbgen2 components library.
if(periph.ramcount > 0 or periph.fifocount > 0 ) then
emit("library wbgen2;");
emit("use wbgen2.all;");
emit("use wbgen2.wbgen2_pkg.all;");
end
emit("");
......@@ -211,13 +211,40 @@ function cgen_generate_vhdl_code(tree)
emit("");
end
-- emits a VHDL combinatorial process
function cgen_vhdl_combprocess(node)
local first_one = true;
emiti();
emitx("process (");
for i,v in pairs(node.slist) do
if(first_one) then
first_one = false;
else
emitx(", ");
end
emitx(v);
end
emit(")");
emit("begin");
indent_right();
recurse(node.code);
indent_left();
emit("end process;");
emit("");
emit("");
end
-- function takes a node and determines it's type, value and range
function node_typesize(node)
local ts = {};
local sig;
-- print(node);
-- if(node==nil) then print(""..node); end
-- if it's a direct signal or a numeric constant, it simply returns it.
......@@ -235,7 +262,13 @@ function cgen_generate_vhdl_code(tree)
ts.l=node.l;
ts.name=sig.name;
ts.type=sig.type;
ts.size = csel(ts.l==nil,1,ts.h-ts.l+1);
if(ts.l == nil) then
ts.size = 1;
ts.type = BIT;
else
ts.size = ts.h-ts.l+1;
end
return ts;
......@@ -320,16 +353,17 @@ function cgen_generate_vhdl_code(tree)
-- dest: slv <= src: signed/unsigned
if(tsd.type == SLV) then
return("std_logic_vector("..gen_subrange(tss.name)..")");
return("std_logic_vector("..gen_subrange(tss)..")");
else die ("unsupported assignment: "..tsd.name.." "..tss.name); end
elseif (tss.type == SLV) then
-- dest: signed/unsigned <= src: slv
if(tsd.type == SIGNED) then
return("signed("..gen_subrange(tss.name)..")");
return("signed("..gen_subrange(tss)..")");
elseif (tsd.type == UNSIGNED) then
return("unsigned("..gen_subrange(tss.name)..")");
print(tss);
return("unsigned("..gen_subrange(tss)..")");
else die ("unsupported assignment: "..tsd.name.." "..tss.name); end
else die ("unsupported assignment: "..tsd.name.." "..tss.name); end
......@@ -344,11 +378,13 @@ function cgen_generate_vhdl_code(tree)
-- source node is an expression? - recurse it
if(tss.type == EXPRESSION) then
emiti();
-- print(gen_subrange(tsd));
emitx(gen_subrange(tsd).." <= ");
recurse({tss.code});
emitx(";\n");
else
-- not an expression? - assign the destination with proper type casting.
-- print(gen_subrange(tsd));
emit(gen_subrange(tsd).." <= "..gen_vhdl_typecvt(tsd, tss)..";");
end
end
......@@ -393,10 +429,13 @@ function cgen_generate_vhdl_code(tree)
-- function generates code for a VHDL binary expression.
function cgen_vhdl_binary_op(node)
local tsa = node_typesize(node.a);
local tsb = node_typesize(node.b);
local op=node.t;
-- emit the left-side operand
if(tsa.type == EXPRESSION) then
emitx("("); recurse({node.a}); emitx(")");
......@@ -422,6 +461,7 @@ function cgen_generate_vhdl_code(tree)
--
function cgen_vhdl_comment(node)
-- print("COMMENT: "..node.str);
emitx("-- "..node.str.."\n");
end
......@@ -525,12 +565,23 @@ function cgen_generate_vhdl_code(tree)
emit("");
end
-- generates VHDL "others => value" construct
function cgen_vhdl_others(node)
emitx("(others => '"..node.val.."')");
end
-- generates VHDL "pin => open" mapping
function cgen_vhdl_openpin(node)
emitx("open");
end
-- the main recursive traversal function.
function recurse(node)
local generators = {
["comment"] = cgen_vhdl_comment;
["syncprocess"] = cgen_vhdl_syncprocess;
["combprocess"] = cgen_vhdl_combprocess;
["assign"] = cgen_vhdl_assign;
["if"] = cgen_vhdl_if;
["eq"] = cgen_vhdl_binary_op;
......@@ -541,14 +592,20 @@ function cgen_generate_vhdl_code(tree)
["not"] = cgen_vhdl_not;
["switch"] = cgen_vhdl_switch;
["instance"] = cgen_vhdl_instance;
["others"] = cgen_vhdl_others;
["openpin"] = cgen_vhdl_openpin;
};
-- print(node);
for i,v in pairs(node) do
-- no type? probably just a block of code. recurse it deeper.
if(v.t == nil) then
recurse(v);
else
local func = generators[v.t];
-- print(v.t);
if(func == nil) then
die("Unimplemented generator: "..v.t);
end
......
......@@ -6,7 +6,7 @@
-- Author : T.W.
-- Company :
-- Created : 2010-02-22
-- Last update: 2010-02-22
-- Last update: 2010-03-15
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
......@@ -33,7 +33,7 @@ entity gpio_port is
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
......@@ -53,7 +53,7 @@ architecture syn of gpio_port is
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
......
......@@ -7,6 +7,8 @@
module main;
reg clk=1;
reg rst=0;
wire [3:0] ones = 'b1111;
always #(`wbclk_period/2) clk <= ~clk;
......@@ -26,10 +28,10 @@ module main;
.wb_data_i (wb_data_o),
.wb_data_o (wb_data_i),
.wb_cyc_i (wb_cyc),
.wb_sel_i (wb_sel),
.wb_stb_i (wb_stb),
.wb_we_i (wb_we),
.wb_ack_o (wb_ack),
.wb_sel_i(ones),
.gpio_pins_b (gpio_pins_b)
);
......
......@@ -6,7 +6,7 @@
-- Author : T.W.
-- Company :
-- Created : 2010-02-22
-- Last update: 2010-02-22
-- Last update: 2010-03-16
-- Platform :
-- Standard : VHDL'87
-------------------------------------------------------------------------------
......@@ -33,7 +33,7 @@ entity gpio_port_async is
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
......@@ -54,7 +54,7 @@ architecture syn of gpio_port_async is
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
......
......@@ -9,6 +9,9 @@ module main;
reg clk=1;
reg clk_async = 1;
reg rst=0;
wire [3:0] ones = 'b1111;
always #(`wbclk_period) clk<=~clk;
always #(`clk_async_period/2) clk_async <= ~clk_async;
......@@ -28,10 +31,11 @@ module main;
.wb_data_i (wb_data_o),
.wb_data_o (wb_data_i),
.wb_cyc_i (wb_cyc),
.wb_sel_i (wb_sel),
.wb_sel_i (ones),
.wb_stb_i (wb_stb),
.wb_we_i (wb_we),
.wb_ack_o (wb_ack),
.gpio_clk_i (clk_async),
.gpio_pins_b (gpio_pins_b)
......
......@@ -6,30 +6,28 @@ 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;
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;
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 component;
end wbgen2_pkg;
#!/bin/bash
./wbgen2.lua regs_with_fields.wb -vo a.vhd -co a.h
#vlib work
#vlib wbgen2
#vcom -work wbgen2 lib/wbgen2_pkg.vhd
#vcom -work wbgen2 lib/wbgen2_dpssram.vhd
#vcom a.vhd
-- here comes our peripheral definition
peripheral {
-- short (human-readable) name for the peripheral.
name = "Test fields and regs";
-- a longer description, if you want
description = "";
-- name of the target VHDL entity to be generated
hdl_entity = "wb_slave_test_regs_fields";
-- prefix for all the generated ports belonging to our peripheral
prefix = "TESTRF";
-- Pin direction register. Readable and writable from the bus, readable from the device.
reg {
name = "Test register SLV/BITs";
description = "Test register SLV/BITs";
prefix = "TRSLV";
field {
name = "Bit field 1";
description = "";
prefix = "BIT1";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Bit field 2";
description = "";
prefix = "BIT2";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Reset bit";
description = "write 1 to reset something";
prefix = "RESET";
type = MONOSTABLE;
};
field {
name = "Counter";
description = "8-bit counter";
prefix = "CNTR";
type = SLV;
size = 8;
align = 8;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "16-bit value";
description = "16-bit SLV";
prefix = "SLV16";
type = SLV;
size = 16;
align = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Test register signed";
prefix = "TSIGNED";
field {
name = "Signed with range";
prefix = "signedrange";
type = SIGNED;
range = {-100, 100};
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Signed 1";
prefix = "signed12bit";
type = SIGNED;
align = 16;
size = 12;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Test register UNsigned";
prefix = "TUNSIGNED";
align = 4;
field {
name = "UnSigned with range";
prefix = "unsignedrange";
type = UNSIGNED;
range = {-200, 250};
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "UNSigned 1";
prefix = "signed13bit";
type = UNSIGNED;
align = 16;
size = 13;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
ram {
name = "memory 1";
prefix = "mem1K";
size = 256;
width = 32;
byte_select = true;
clock = "clk1_i";
wrap_bits = 1;
access_bus = READ_WRITE;
access_dev = READ_WRITE;
};
ram {
name = "memory 2";
prefix = "mem2K";
size = 1024;
width = 16;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
This diff is collapsed.
......@@ -15,6 +15,7 @@ dofile(wbgen2_libdir.."/wbgen_common.lua");
dofile(wbgen2_libdir.."/cgen_common.lua");
dofile(wbgen2_libdir.."/cgen_vhdl.lua");
dofile(wbgen2_libdir.."/cgen_verilog.lua");
dofile(wbgen2_libdir.."/cgen_c_headers.lua");
dofile(wbgen2_libdir.."/wbgen_regbank.lua");
dofile(wbgen2_libdir.."/wbgen_rams.lua");
dofile(wbgen2_libdir.."/target_wishbone.lua");
......@@ -57,7 +58,7 @@ function parse_args(arg)
options.output_hdl_file = chk_nil(arg[n+1], "HDL output filename expected");
n=n+2;
elseif(sw == "-co") then
output_c_file = chk_nil(arg[n+1], "C header output filename expected");
options.output_c_header_file = chk_nil(arg[n+1], "C header output filename expected");
n=n+2;
elseif(sw == "--gen-reg-constants") then
vhdl_gen_reg_constants = true;
......@@ -94,17 +95,29 @@ foreach_reg( fix_prefix );
periph = fix_prefix(periph);
wbgen_count_subblocks();
foreach_field(calc_size);
foreach_reg(check_max_size);
foreach_field(calc_field_offsets);
foreach_reg(calc_address_sizes);
assign_addresses();
tree=gen_bus_logic_wishbone();
cgen_build_signals_ports();
cgen_generate_hdl_init(options.output_hdl_file)
cgen_generate_vhdl_code(tree);
cgen_generate_hdl_done();
if(options.output_hdl_file ~= nil) then
cgen_generate_init(options.output_hdl_file)
cgen_generate_vhdl_code(tree);
cgen_generate_done();
end
if(options.output_c_header_file ~= nil) then
cgen_generate_init(options.output_c_header_file)
cgen_generate_c_header_code();
cgen_generate_done();
end
......@@ -165,6 +165,9 @@ function calc_field_offsets(field, reg)
reg.current_offset = ofs + field.size;
field.offset = ofs;
if(reg.num_fields == nil) then reg.num_fields = 0; end
reg.num_fields = reg.num_fields + 1;
if( reg.__type == TYPE_REG and reg.current_offset > DATA_BUS_WIDTH ) then
die ("Total size of register '"..reg.name.."' ("..reg.current_offset..") exceeds data bus width ("..DATA_BUS_WIDTH..")");
......@@ -322,7 +325,8 @@ function calc_address_sizes(reg)
die("RAM '"..reg.name.."' data width exceeds WB data bus width");
end
reg.select_bits = num_rams + 1;
reg.select_bits = csel(periph.regcount+periph.fifocount == 0, num_rams, num_rams + 1);
num_rams = num_rams + 1;
end
......@@ -418,3 +422,28 @@ function remove_duplicates(t)
end
end
function wbgen_count_subblocks()
local ramcount = 0;
local fifocount = 0;
local regcount = 0;
-- count the RAMs & FIFOs in the design
foreach_reg(function(reg)
if(reg.__type == TYPE_RAM) then
ramcount = ramcount + 1;
end
if(reg.__type == TYPE_FIFO) then
fifocount = fifocount + 1;
end
if(reg.__type == TYPE_REG) then
regcount = regcount + 1;
end
end
);
periph.ramcount = ramcount;
periph.fifocount = fifocount;
periph.regcount = regcount;
end
#!/usr/bin/lua
function gen_code_ram(ram)
local prefix = string.lower(periph.hdl_prefix.."_"..ram.hdl_prefix);
local maps = {};
print("GENRAMCODE!"..ram.name);
function ram_wire_core_ports(ram)
local prefix = ram.full_prefix;
-- 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
if(match(ram.access_dev, {READ_ONLY, READ_WRITE})) then -- RAM is readable from the core - wire the data output and read strobe signals
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");
table_join(ram.maps, { vpm ("data_b_o", prefix.."_data_o");
vpm ("rd_b_i", prefix.."_rd_i"); } );
else -- ram is not readable - the read strobe low and leave the data output open
table_join(ram.maps, { vpm ("data_b_o", vopenpin());
vpm ("rd_b_i", vi(allzeros, 0)) });
end
if(match(ram.access_dev, {WRITE_ONLY, READ_WRITE})) then
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"); });
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(ram.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
table_join(ram.maps, { vpm ("bwsel_b_i", prefix.."_bwsel_i"); } );
else
table_join(ram.maps, { vpm ("bwsel_b_i", vi("allones", math.floor(ram.width/8)-1, 0)); } );
end
else
table_join(ram.maps, { vpm ("bwsel_b_i", vi("allones", math.floor(ram.width/8)-1, 0));
vpm ("data_b_i", vi("allzeros", ram.width-1 ,0));
vpm ("wr_b_i", vi("allzeros", 0)) });
end
end
table_join(maps, { vpm ("addr_a_i", vi("rwaddr_reg", log2up(ram.size)-1, 0)) });
if(match(ram.access_bus, {READ_ONLY, READ_WRITE})) then
function ram_wire_bus_ports(ram)
local prefix = ram.full_prefix;
-- RAM is readable from the bus?
if(match(ram.access_bus, {READ_ONLY, READ_WRITE})) then -- yes: wire rd strobe and data output
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));
table_join(ram.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); });
else -- not readable? - set read strobe to zero and leave the data output open
table_join(ram.maps, { vpm ("rd_a_i", vi("allzeros", 0)),
vpm ("data_a_o", vopenpin()) });
end
-- RAM is writable from the bus?
if(match(ram.access_bus, {WRITE_ONLY, READ_WRITE})) then
table_join(ram.signals, { signal(BIT, 0, prefix.."_wr_int") } );
table_join(maps, { vpm ("data_a_i", vi("wrdata_reg", ram.width-1, 0));
table_join(ram.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
table_join(ram.maps, { vpm ("bwsel_a_i", vi("bwsel_reg", math.floor(ram.width/8)-1, 0)); } );
else
table_join(ram.maps, { vpm ("bwsel_a_i", vi("allones", math.floor(ram.width/8)-1, 0)); } );
end
else
table_join(ram.maps, { vpm ("bwsel_a_i", vi("allones", math.floor(ram.width/8)-1, 0));
vpm ("data_a_i", vi("allzeros", ram.width-1 ,0));
vpm ("wr_a_i", vi("allzeros", 0)) });
end
end
function gen_code_ram(ram)
local prefix = string.lower(periph.hdl_prefix.."_"..ram.hdl_prefix);
-- generate the RAM-related ports
ram.full_prefix = prefix;
ram.signals = {};
ram.maps = {};
ram.ports = { port (SLV, ram.addr_bits - ram.wrap_bits, "in", prefix.."_addr_i", "Ports for RAM: "..ram.name ) };
ram.reset_code_main = {};
-- wire the obligartory signals - address busses and clocks
table_join(ram.maps, { vpm ("clk_a_i", "bus_clock_int");
vpm ("clk_b_i", csel(ram.clock ~= nil, ram.clock, "bus_clock_int"));
vpm ("addr_b_i", prefix.."_addr_i");
vpm ("addr_a_i", vi("rwaddr_reg", log2up(ram.size)-1, 0));
});
-- evaluate the access flags (from the core) and wire the core signals to appropriate ports
ram_wire_core_ports(ram);
-- do the same for the bus signals
ram_wire_bus_ports(ram);
-- fill in all the generic mappings
table_join(maps, { vgm ("g_data_width", ram.width);
table_join(ram.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"));
});
-- instantiate the RAM.
ram.extra_code = { vcomment ("RAM block instantiation for memory: "..ram.name);
vinstance (prefix.."_raminst", "wbgen2_dpssram", maps ); };
vinstance (prefix.."_raminst", "wbgen2_dpssram", ram.maps );
};
end
......@@ -45,7 +45,7 @@ function gen_hdl_code_monostable(field, reg)
field.ports = { port(BIT, 0, "out", prefix.."_o", "Port for MONOSTABLE field: '"..field.name.."' in reg: '"..reg.name.."'" ) };
field.acklen = 3;
field.extra_code = vsyncprocess("wb_clk_i", "rst_n_i", {
field.extra_code = vsyncprocess("bus_clock_int", "rst_n_i", {
vreset (0, {
va(prefix.."_dly0", 0);
va(prefix.."_o", 0);
......@@ -176,7 +176,7 @@ function gen_hdl_code_bit(field, reg)
field.reset_code_main = { va(prefix.."_int", 0) };
field.extra_code = { vcomment("synchronizer chain for field : "..field.name.." (type RW/RO, wb_clk_i <-> "..field.clock..")");
field.extra_code = { vcomment("synchronizer chain for field : "..field.name.." (type RW/RO, bus_clock_int <-> "..field.clock..")");
vsyncprocess(field.clock, "rst_n_i", {
vreset(0, {
va(prefix.."_o", 0);
......@@ -204,7 +204,7 @@ function gen_hdl_code_bit(field, reg)
field.reset_code_main = { };
field.extra_code = { vcomment("synchronizer chain for field : "..field.name.." (type RO/WO, "..field.clock.." -> wb_clk_i)");
field.extra_code = { vcomment("synchronizer chain for field : "..field.name.." (type RO/WO, "..field.clock.." -> bus_clock_int)");
vsyncprocess(field.clock, "rst_n_i", {
vreset(0, {
va(prefix.."_sync0", 0);
......@@ -266,14 +266,14 @@ function gen_hdl_code_bit(field, reg)
field.ackgen_code_pre = { va(prefix.."_lw", prefix.."_lw_delay");
va(prefix.."_lw_delay", 0);
vif(vand(vequal("ack_cntr", 1), vequal(prefix.."_lw_read_in_progress", 1)), {
vif(vand(vequal(vi("ack_sreg", 1), 1), vequal(prefix.."_lw_read_in_progress", 1)), {
va(vi("rddata_reg", field.offset), prefix.."_int_read");
va(prefix.."_lw_read_in_progress", 0);
});
};
field.extra_code = { vcomment("asynchronous BIT register : "..field.name.." (type RW/WO, "..field.clock.." <-> wb_clk_i)");
field.extra_code = { vcomment("asynchronous BIT register : "..field.name.." (type RW/WO, "..field.clock.." <-> bus_clock_int)");
vsyncprocess(field.clock, "rst_n_i", {
vreset(0, {
va(prefix.."_lw_s0", 0);
......@@ -399,7 +399,7 @@ function gen_hdl_code_slv(field, reg)
va(prefix.."_swb_delay", 0); };
field.extra_code = { vcomment("asynchronous "..fieldtype_2_vhdl[field.type].." register : "..field.name.." (type RW/RO, "..field.clock.." <-> wb_clk_i)");
field.extra_code = { vcomment("asynchronous "..fieldtype_2_vhdl[field.type].." register : "..field.name.." (type RW/RO, "..field.clock.." <-> bus_clock_int)");
vsyncprocess(field.clock, "rst_n_i", {
vreset(0, {
va(prefix.."_swb_s0", 0);
......@@ -446,13 +446,13 @@ function gen_hdl_code_slv(field, reg)
field.ackgen_code_pre = { va(prefix.."_lwb", prefix.."_lwb_delay");
va(prefix.."_lwb_delay", 0);
vif(vand(vequal("ack_cntr", 1), vequal(prefix.."_lwb_in_progress", 1)), {
vif(vand(vequal(vi("ack_sreg", 1), 1), vequal(prefix.."_lwb_in_progress", 1)), {
va(vir("rddata_reg", field), prefix.."_int");
va(prefix.."_lwb_in_progress", 0);
});
};
field.extra_code = { vcomment("asynchronous "..fieldtype_2_vhdl[field.type].." register : "..field.name.." (type RO/WO, "..field.clock.." <-> wb_clk_i)"),
field.extra_code = { vcomment("asynchronous "..fieldtype_2_vhdl[field.type].." register : "..field.name.." (type RO/WO, "..field.clock.." <-> bus_clock_int)"),
vsyncprocess(field.clock, "rst_n_i", {
vreset(0, {
va(prefix.."_lwb_s0", 0);
......@@ -520,13 +520,13 @@ function gen_hdl_code_slv(field, reg)
field.ackgen_code_pre = { va(prefix.."_lw", prefix.."_lw_delay");
va(prefix.."_lw_delay", 0);
vif (vand(vequal("ack_cntr", 1), vequal(prefix.."_lw_read_in_progress", 1)), {
vif (vand(vequal(vi("ack_sreg", 1), 1), vequal(prefix.."_lw_read_in_progress", 1)), {
va(vir("rddata_reg", field), prefix.."_int_read");
});
va(prefix.."_lw_read_in_progress", 0);
};
field.extra_code = { vcomment("asynchronous "..fieldtype_2_vhdl[field.type].." register : "..field.name.." (type RW/WO, "..field.clock.." <-> wb_clk_i)");
field.extra_code = { vcomment("asynchronous "..fieldtype_2_vhdl[field.type].." register : "..field.name.." (type RW/WO, "..field.clock.." <-> bus_clock_int)");
vsyncprocess(field.clock, "rst_n_i", {
vreset(0, {
va(prefix.."_lw_s0", 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