Commit 6ee9c2e0 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

final updates to wbgen2 before it gets replaced by Cheby:

- record_full interface option: use general cores's library WB interface types
  to simplify connection of the cores. Enabled by -H record_full option
- use byte addressing for WB address (in record_full mode)
- allow specifying package name with record/component definitions (hdl_package field in the peripheral record)
- fixed indentation & formatting of produced VHDL package files
- include VHDL component declaration in the package files
parent cc5a5c00
...@@ -217,6 +217,7 @@ end ...@@ -217,6 +217,7 @@ end
VPORT_WB = 1; VPORT_WB = 1;
VPORT_REG = 2; VPORT_REG = 2;
VPORT_CLK_RST = 3;
-- constructor for a HDL port -- constructor for a HDL port
function port(type, nbits, dir, name, comment, extra_flags) function port(type, nbits, dir, name, comment, extra_flags)
...@@ -237,9 +238,15 @@ function port(type, nbits, dir, name, comment, extra_flags) ...@@ -237,9 +238,15 @@ function port(type, nbits, dir, name, comment, extra_flags)
if(extra_flags == VPORT_WB) then if(extra_flags == VPORT_WB) then
t.is_wb = true; t.is_wb = true;
t.is_reg_port = false; t.is_reg_port = false;
t.is_clk_rst = false;
elseif(extra_flags == VPORT_REG) then elseif(extra_flags == VPORT_REG) then
t.is_wb = false; t.is_wb = false;
t.is_reg_port = true; t.is_reg_port = true;
t.is_clk_rst = false;
elseif(extra_flags == VPORT_CLK_RST) then
t.is_wb = false;
t.is_reg_port = false;
t.is_clk_rst = true;
else else
t.is_wb =false t.is_wb =false
t.is_reg_port = false; t.is_reg_port = false;
......
...@@ -18,6 +18,14 @@ fieldtype_2_vhdl[ENUM] = "std_logic_vector"; ...@@ -18,6 +18,14 @@ fieldtype_2_vhdl[ENUM] = "std_logic_vector";
fieldtype_2_vhdl[SLV] = "std_logic_vector"; fieldtype_2_vhdl[SLV] = "std_logic_vector";
function get_pkg_name()
if (periph.hdl_package) then
return periph.hdl_package
else
return periph.hdl_prefix.."_wbgen2_pkg";
end
end
-- generates a string containing VHDL-compatible numeric constant of value [value] and size [numbits] -- generates a string containing VHDL-compatible numeric constant of value [value] and size [numbits]
function gen_vhdl_bin_literal(value, numbits) function gen_vhdl_bin_literal(value, numbits)
if(numbits == 1) then if(numbits == 1) then
...@@ -50,9 +58,16 @@ function strip_periph_prefix(s) ...@@ -50,9 +58,16 @@ function strip_periph_prefix(s)
return string.gsub(s, "^"..periph.hdl_prefix.."\_", "") return string.gsub(s, "^"..periph.hdl_prefix.."\_", "")
end end
function strip_wb_prefix(s)
local t = string.gsub(s, "^wb\_", "")
t = string.gsub(t, "_o$","")
t = string.gsub(t, "_i$","")
return t
end
-- fixme: do this neatly -- fixme: do this neatly
function port2record(s) function port2record(s)
if(options.hdl_reg_style ~= "record") then if(options.hdl_reg_style == "signals") then
return s return s
end end
...@@ -60,14 +75,23 @@ function port2record(s) ...@@ -60,14 +75,23 @@ function port2record(s)
if(port.name == s and port.is_reg_port) then if(port.name == s and port.is_reg_port) then
return csel(port.dir=="in", "regs_i.", "regs_o.")..strip_periph_prefix(s) return csel(port.dir=="in", "regs_i.", "regs_o.")..strip_periph_prefix(s)
end end
if(port.name == s and port.is_wb and options.hdl_reg_style == "record_full") then
if s == "wb_int_o" then
return "int_o";
end
return csel(port.dir=="in", "slave_i.", "slave_o.")..strip_wb_prefix(s)
end
end end
return s return s
end end
function cgen_vhdl_package() function cgen_vhdl_package()
local pkg_name = periph.hdl_prefix.."_wbgen2_pkg";
emit("package "..pkg_name.." is") emit("package "..get_pkg_name().." is")
indent_right(); indent_right();
emit(""); emit("");
...@@ -84,50 +108,68 @@ function cgen_vhdl_package() ...@@ -84,50 +108,68 @@ function cgen_vhdl_package()
cgen_vhdl_port_struct("out"); cgen_vhdl_port_struct("out");
indent_left();
local typename = "t_"..periph.hdl_prefix.."_in_registers"; local typename = "t_"..periph.hdl_prefix.."_in_registers";
emit("");
emit("function \"or\" (left, right: "..typename..") return "..typename..";"); emit("function \"or\" (left, right: "..typename..") return "..typename..";");
emit("function f_x_to_zero (x:std_logic) return std_logic;"); emit("function f_x_to_zero (x:std_logic) return std_logic;");
emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector;"); emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector;");
emit("");
cgen_vhdl_interface_declaration("component")
indent_left(); indent_left();
indent_left();
emit("end package;"); emit("end package;");
emit(""); emit("");
emit("package body "..pkg_name.." is"); emit("package body "..get_pkg_name().." is");
indent_right();
emit("function f_x_to_zero (x:std_logic) return std_logic is"); emit("function f_x_to_zero (x:std_logic) return std_logic is");
emit("begin") emit("begin")
indent_right();
emit("if x = '1' then") emit("if x = '1' then")
indent_right();
emit("return '1';") emit("return '1';")
indent_left();
emit("else") emit("else")
indent_right();
emit("return '0';") emit("return '0';")
indent_left();
emit("end if;") emit("end if;")
indent_left();
emit("end function;"); emit("end function;");
emit("")
emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector is"); emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector is");
emit("variable tmp: std_logic_vector(x'length-1 downto 0);"); indent_right();
emit("variable tmp: std_logic_vector(x'length-1 downto 0);");
indent_left();
emit("begin"); emit("begin");
indent_right();
emit("for i in 0 to x'length-1 loop"); emit("for i in 0 to x'length-1 loop");
indent_right();
emit("if(x(i) = 'X' or x(i) = 'U') then"); emit("if(x(i) = 'X' or x(i) = 'U') then");
indent_right();
emit("tmp(i):= '0';"); emit("tmp(i):= '0';");
indent_left();
emit("else"); emit("else");
indent_right();
emit("tmp(i):=x(i);"); emit("tmp(i):=x(i);");
indent_left();
emit("end if; "); emit("end if; ");
indent_left();
emit("end loop; "); emit("end loop; ");
emit("return tmp;"); emit("return tmp;");
indent_left();
emit("end function;"); emit("end function;");
emit("");
emit("function \"or\" (left, right: "..typename..") return "..typename.." is"); emit("function \"or\" (left, right: "..typename..") return "..typename.." is");
indent_right();
emit("variable tmp: "..typename..";"); emit("variable tmp: "..typename..";");
indent_left();
emit("begin"); emit("begin");
indent_right();
for i=1,table.getn(g_portlist) do for i=1,table.getn(g_portlist) do
local port = g_portlist[i]; local port = g_portlist[i];
...@@ -137,8 +179,10 @@ function cgen_vhdl_package() ...@@ -137,8 +179,10 @@ function cgen_vhdl_package()
end end
end end
emit("return tmp;"); emit("return tmp;");
indent_left();
emit("end function;"); emit("end function;");
indent_left();
emit("");
emit("end package body;"); emit("end package body;");
end end
...@@ -168,8 +212,8 @@ function cgen_vhdl_port_struct(direction) ...@@ -168,8 +212,8 @@ function cgen_vhdl_port_struct(direction)
emit(line); emit(line);
end end
emit("end record;");
indent_left(); indent_left();
emit("end record;");
emit(""); emit("");
emit("constant c_"..periph.hdl_prefix.."_"..direction.."_registers_init_value: t_"..periph.hdl_prefix.."_"..direction.."_registers := ("); emit("constant c_"..periph.hdl_prefix.."_"..direction.."_registers_init_value: t_"..periph.hdl_prefix.."_"..direction.."_registers := (");
indent_right(); indent_right();
...@@ -188,7 +232,8 @@ function cgen_vhdl_port_struct(direction) ...@@ -188,7 +232,8 @@ function cgen_vhdl_port_struct(direction)
emit(line); emit(line);
end end
emit(");"); indent_left();
emit(");");
end end
...@@ -219,20 +264,15 @@ function cgen_vhdl_header(file_name) ...@@ -219,20 +264,15 @@ function cgen_vhdl_header(file_name)
emit("use work.wbgen2_pkg.all;"); emit("use work.wbgen2_pkg.all;");
end end
if(options.hdl_reg_style == "record_full") then
emit("use work.wishbone_pkg.all;");
end
emit(""); emit("");
end end
function cgen_vhdl_interface_declaration(keyword)
-- function generates VHDL entity header (ports and generics) and beginning of ARCHITECTURE block (signal and constant definitions). emit (keyword.." "..periph.hdl_entity.." is");
function cgen_vhdl_entity()
local last;
if(options.hdl_reg_style == "record") then
emit("use work."..periph.hdl_prefix.."_wbgen2_pkg.all;");
emit("\n");
end
emit ("entity "..periph.hdl_entity.." is");
indent_right(); indent_right();
if(table.getn(g_optlist) ~= 0) then if(table.getn(g_optlist) ~= 0) then
...@@ -262,7 +302,15 @@ function cgen_vhdl_entity() ...@@ -262,7 +302,15 @@ function cgen_vhdl_entity()
for i=1,table.getn(g_portlist) do for i=1,table.getn(g_portlist) do
local port = g_portlist[i]; local port = g_portlist[i];
if(options.hdl_reg_style == "signals" or not port.is_reg_port) then local generate = true;
if( options.hdl_reg_style == "record" and port.is_reg_port ) then
generate = false;
elseif ( options.hdl_reg_style == "record_full" and (port.is_reg_port or port.is_wb) ) then
generate = false;
end
if(generate) then
-- if we have a comment associated with current port, let's emit it before the port definition. -- if we have a comment associated with current port, let's emit it before the port definition.
if(port.comment ~= nil and port.comment ~= "") then if(port.comment ~= nil and port.comment ~= "") then
...@@ -278,24 +326,50 @@ function cgen_vhdl_entity() ...@@ -278,24 +326,50 @@ function cgen_vhdl_entity()
end end
-- eventually append a semicolon -- eventually append a semicolon
line=line..csel((i == table.getn(g_portlist)) and not (options.hdl_reg_style == "record"), "", ";"); line=line..csel((i == table.getn(g_portlist)) and not (options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full"), "", ";");
-- and spit out the line -- and spit out the line
emit(line); emit(line);
end end
end end
if(options.hdl_reg_style == "record") then if(options.hdl_reg_style == "record_full") then
emit(string.format("%-40s : %-6s %s", "regs_i", "in", "t_"..periph.hdl_prefix.."_in_registers;")); emit(string.format("%-40s : %-6s %s;", "slave_i", "in", "t_wishbone_slave_in"));
emit(string.format("%-40s : %-6s %s", "regs_o", "out", "t_"..periph.hdl_prefix.."_out_registers")); emit(string.format("%-40s : %-6s %s;", "slave_o", "out", "t_wishbone_slave_out"));
emit(string.format("%-40s : %-6s %s;", "int_o", "out", "std_logic"));
end
if(options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full") then
emit(string.format("%-40s : %-6s %s;", "regs_i", "in", "t_"..periph.hdl_prefix.."_in_registers"));
emit(string.format("%-40s : %-6s %s", "regs_o", "out", "t_"..periph.hdl_prefix.."_out_registers"));
end end
indent_left(); indent_left();
emit(");"); emit(");");
indent_left(); indent_left();
emit("end "..periph.hdl_entity..";");
if ( keyword == "component") then
emit("end component;");
else
emit("end "..periph.hdl_entity..";");
end
emit(""); emit("");
end
-- function generates VHDL entity header (ports and generics) and beginning of ARCHITECTURE block (signal and constant definitions).
function cgen_vhdl_entity()
local last;
if(options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full") then
emit("use work."..get_pkg_name()..".all;");
emit("\n");
end
cgen_vhdl_interface_declaration("entity")
-- generate the ARCHITECTURE block with signal definitions -- generate the ARCHITECTURE block with signal definitions
emit("architecture syn of "..periph.hdl_entity.." is"); emit("architecture syn of "..periph.hdl_entity.." is");
...@@ -853,7 +927,7 @@ function cgen_generate_vhdl_code(tree) ...@@ -853,7 +927,7 @@ function cgen_generate_vhdl_code(tree)
end end
end end
if(options.hdl_reg_style == "record" and options.output_package_file ~= nil) then if((options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full") and options.output_package_file ~= nil) then
cgen_generate_init(options.output_package_file); cgen_generate_init(options.output_package_file);
cgen_new_snippet(); cgen_new_snippet();
cgen_vhdl_header(options.output_package_file); cgen_vhdl_header(options.output_package_file);
......
...@@ -8,8 +8,8 @@ MODE_PIPELINED=2 ...@@ -8,8 +8,8 @@ MODE_PIPELINED=2
function gen_pipelined_wb_ports(mode) function gen_pipelined_wb_ports(mode)
local ports = { local ports = {
port(BIT, 0, "in", "rst_n_i", "", VPORT_WB), port(BIT, 0, "in", "rst_n_i", "", 0),
port(BIT, 0, "in", "clk_sys_i", "", VPORT_WB), port(BIT, 0, "in", "clk_sys_i", "", 0),
}; };
if(address_bus_width > 0 ) then if(address_bus_width > 0 ) then
...@@ -23,7 +23,9 @@ function gen_pipelined_wb_ports(mode) ...@@ -23,7 +23,9 @@ function gen_pipelined_wb_ports(mode)
port(SLV, math.floor((DATA_BUS_WIDTH+7)/8), "in", "wb_sel_i", "", VPORT_WB), port(SLV, math.floor((DATA_BUS_WIDTH+7)/8), "in", "wb_sel_i", "", VPORT_WB),
port(BIT, 0, "in", "wb_stb_i", "", VPORT_WB), port(BIT, 0, "in", "wb_stb_i", "", VPORT_WB),
port(BIT, 0, "in", "wb_we_i", "", VPORT_WB), port(BIT, 0, "in", "wb_we_i", "", VPORT_WB),
port(BIT, 0, "out", "wb_ack_o", "", VPORT_WB) port(BIT, 0, "out", "wb_ack_o", "", VPORT_WB),
port(BIT, 0, "out", "wb_err_o", "", VPORT_WB),
port(BIT, 0, "out", "wb_rty_o", "", VPORT_WB)
}); });
if(mode == MODE_PIPELINED) then if(mode == MODE_PIPELINED) then
...@@ -295,12 +297,19 @@ function gen_bus_logic_pipelined_wb(mode) ...@@ -295,12 +297,19 @@ function gen_bus_logic_pipelined_wb(mode)
if(address_bus_width > 0) then if(address_bus_width > 0) then
table_join(code, { va("rwaddr_reg", "wb_adr_i"); }); if(options.hdl_reg_style == "record_full") then
table_join(code, { va("rwaddr_reg", vi("wb_adr_i", address_bus_width + 2 - 1, 2) ); } );
else
table_join(code, { va("rwaddr_reg", "wb_adr_i" ); } );
end
else else
table_join(code, { va("rwaddr_reg", vothers(0)); }); table_join(code, { va("rwaddr_reg", vothers(0)); });
end end
table_join(code, { va("wb_stall_o", vand(vnot(vi("ack_sreg", 0)), vand("wb_stb_i","wb_cyc_i")))}); table_join(code, { va("wb_stall_o", vand(vnot(vi("ack_sreg", 0)), vand("wb_stb_i","wb_cyc_i")))});
table_join(code, { va("wb_err_o", 0 ) } );
table_join(code, { va("wb_rty_o", 0 ) } );
table_join(code, { vcomment("ACK signal generation. Just pass the LSB of ACK counter."); table_join(code, { vcomment("ACK signal generation. Just pass the LSB of ACK counter.");
va("wb_ack_o", vi("ack_sreg", 0)); va("wb_ack_o", vi("ack_sreg", 0));
......
This diff is collapsed.
...@@ -44,7 +44,7 @@ local commands_string = [[options: ...@@ -44,7 +44,7 @@ local commands_string = [[options:
-s, --cstyle=STYLE Set the style of register bank in generated C headers -s, --cstyle=STYLE Set the style of register bank in generated C headers
Valid values for STYLE: {struct, defines} Valid values for STYLE: {struct, defines}
-H, --hstyle=STYLE Set the style of register signals in generated VHDL/Verilog file -H, --hstyle=STYLE Set the style of register signals in generated VHDL/Verilog file
Valid values for STYLE: {signals, record} Valid values for STYLE: {signals, record, record_full}
-K, --constco=FILE Populate FILE with Verilog output (mainly constants) -K, --constco=FILE Populate FILE with Verilog output (mainly constants)
-v, --version Show version information -v, --version Show version information
-V, --vo=FILE Write the slave's generated HDL code to FILE -V, --vo=FILE Write the slave's generated HDL code to FILE
...@@ -120,7 +120,7 @@ function parse_args(arg) ...@@ -120,7 +120,7 @@ function parse_args(arg)
elseif key == "p" then elseif key == "p" then
options.output_package_file = value options.output_package_file = value
elseif key == "H" then elseif key == "H" then
if (value ~= "signals" and value ~= "record") then if (value ~= "signals" and value ~= "record" and value ~= "record_full") then
die("Unknown register style: "..value); die("Unknown register style: "..value);
end end
options.hdl_reg_style = value options.hdl_reg_style = value
...@@ -209,7 +209,7 @@ if(options.output_hdl_file ~= nil) then ...@@ -209,7 +209,7 @@ if(options.output_hdl_file ~= nil) then
if (options.lang == "vhdl") then if (options.lang == "vhdl") then
cgen_generate_vhdl_code(tree); cgen_generate_vhdl_code(tree);
elseif (options.lang == "verilog") then elseif (options.lang == "verilog") then
-- cgen_generate_verilog_code(tree); cgen_generate_verilog_code(tree);
end end
end 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