Hierarchical Partitioning in IDS-Integrate
Rahul Parashar
Introduction
The hierarchical partitioning feature allows users to add a hierarchy level by moving one or more blocks at the peer level to a new block. In a typical use case, users read a hierarchical RTL module, and combine one or more instances of some modules into another newly created module to add one level of hierarchy. It is shown in the example below.
Consider a design as shown in the diagram where top_soc is a top-level module and it has instances of three blocks blkA, blkB, and blKC with the instance names blkA_inst, blkB_inst, and blkC_inst respectively.
In the example script provided below, the top_soc is read using the soc_read API along with its instantiated blocks. Then, the soc_move API is used for hierarchical partitioning.
Python Script:
soc_read("+libext+.v", "top", search_path="ipread", file="top_soc.v", y="ipread", name="top_soc") soc_move("create",source=["blkA_inst","blkB_inst"],dest="blkD") soc_generate("compact", out=["v"],dir="hierout")
After hierarchical partitioning, the updated top_soc is saved as RTL along with the RTL of the newly created block. The diagram below shows the updated top_soc.
Reading hierarchy to a certain level
A top-level RTL may have a very deep hierarchy for complex designs. While reading such RTL for hierarchical partitioning using the soc_read command, parsing the whole hierarchy is unnecessary as it will be time-consuming.
The soc_read API have an option that allows users to specify the hierarchy depth level to parse starting from the top level. The soc_read syntax can be updated as follows:
soc_read("+libext+.v", "top",search_path="<search-path>", file="<file-name>", y="<include-directory>", depth="<depth-level>")
Where,
- depth: this option allows users to specify the depth level up to which the hierarchy should be parsed starting from the top level. It should be a number with the topmost level as 0.
Multiple Level Hierarchical Partitioning:
Multiple Level Hierarchical Partitioning feature allows users to add a hierarchy level by moving one or more blocks at the hierarchy level to a new block or existing block. In the typical use case, users read a hierarchical RTL module, referred to as a top module, and combine one or more instances of some modules into another newly created module to add one level of hierarchy.
Scenario 1:- Consider a design as shown in the diagram where top_soc is a top-level module and it has instances of two blocks M3, sub_blk, and with the instance names inst3 and sub_blk_inst respectively. And sub_blk has an instance of block M1 with the two instances names inst1 and inst2 respectively.
In the example script provided below, the top_soc is read using the soc_read API along with its instantiated blocks. Then, the soc_move API is used for Multiple-level hierarchical partitioning.
Python Script:
soc_read("+libext+.v", "top", search_path="ipread", file="top_soc.v", y="ipread", name="top_soc") soc_move("create",source="sub_blk_inst/inst1",dest="movingBlk") soc_generate("compact", out=["v"],dir="hierout")
Scenario 2 :
Consider a design as shown in the diagram where top_soc is a top level module and it has instances of two blocks sub_blk, blkA and with the instance names instsub and instA respectively. And blkA has instance of block blkB with the instance names instB respectively. And blkB has instances of two blocks blkC and blkD with the instance names instC and instD respectively.
Python Script:
soc_read("+libext+.v", "top", search_path="ipread", file="top_soc.v", y="ipread", name="top_soc") soc_move("create",source="instA/instB/instC",dest="top_soc") soc_generate("compact", out=["v"],dir="hierout")
Conclusion:
To summarize, the Hierarchical Partitioning in IDS-Integrate is used to manipulate the hierarchy at any level the user wants.
Generation of Assertions from Connectivity Spec using IDS-Integrate
Ravi Kumar
In IDS-Integrate, users can easily input instructions using TCL or Python . The tool automatically generates assertions that focus on key connectivity aspects like ad-hoc connections, bus aggregations, bridge connections. With a special output feature called “formal,” users can create detailed assertions specifically for integrated circuits.
For example, consider creating assertions for the connectivity of bus aggregation logic in an SoC. Suppose there is an APB bus at the top or wrapper block, sending signals to four different child blocks. The assertions generated will ensure that the bus aggregation logic works correctly within the design. Users can further customise and expand these assertions to fit the specific needs of their SoC design.
This approach simplifies the process, allowing users to ensure their designs are reliable and efficient with ease.
Input: Shown below is a python script for setting up and generating a System-on-Chip (SoC) design. This script creates a simple SoC design with a top-level “chip” block and a child “block_inst”. It connects the two using an APB bus and generates the design files needed for both implementation and formal verification.
soc_clean() soc_set("debug") soc_create( name="block", bus="apb") soc_create("top",name="chip", bus="apb") soc_add(parent="chip", name="block", inst="block_inst" ) soc_connect(source="chip", dest="block_inst",bus="apb" ) soc_generate("compact",out=["sv","arv_formal"],dir="formal_s")
Output – It will generate the following files –
- sv
- formal.sv
- sv
- sv
- formal.sv
block.sv – The block module is designed to interface with a bus, handling communication between the bus and the internal logic of the block.
module block #( //parameter declaration )( //input output port declaration of bus ); endmodule
chip.formal.sv – The primary purpose of this file is to verify the connectivity between the top-level module and the block instance (block_inst). By asserting these connections, the designer ensures that the BUS signals from the top-level module are correctly passed down to the block_inst. This is crucial for ensuring that the communication between the two modules works as intended.
module chip_ids_assert #( //parameter decelaration )( //input deceleration of BUS signals ); clocking cb @(posedge pclk); property block_connection_check1; pclk |-> block_inst.pclk; endproperty property block_connection_check2; paddr |-> block_inst.paddr; endproperty property block_connection_check12; pslverr |->block_inst.pslverr; endproperty endclocking block_connection_check1_assert : assert property(cb.block_connection_check1); block_connection_check2_assert : assert property(cb.block_connection_check2); block_connection_check12_assert : assert property(cb.block_connection_check12); endmodule
Clocking Block – This module checks and asserts the correct connection of BUS signals between a chip and its block instance using SystemVerilog assertions.
Properties – This module verifies that all APB signals between a chip and its block instance are correctly connected by using SystemVerilog assertions to ensure proper signal routing.
Assertions – This module uses assertions to verify that each BUS signal in the block instance correctly matches the corresponding signal in the chip during simulation.
chip.sv – This file defines a chip module that instantiates a block module, passing BUS signals between them. It serves as a top-level wrapper that connects the chip’s inputs and outputs to the corresponding signals in the block instance.
`include "block.sv" module chip #( //parameter deceleration )( //input & output port deceleration of bus signals ); block block_inst( //mapping of bus signals from child to parent ); endmodule
chip_top_onespin.sv – This file binds assertions to the chip module to verify its signal connections during formal verification.
`include "chip.sv" `include "chip.formal.sv" module chip_onespin; bind chip chip_ids_assert chip_assert (.*); endmodule
chip1_cover.formal.sv – This module defines assertions to verify that signals in the block_inst are correctly connected and match the expected values during simulation. Each property checks a specific signal connection, and assertions ensure these properties hold true.
module chip_ids_assert #( //parameter declaration )( //port deceleration of BUS signals ); clocking cb @(posedge pclk); property block_connection_check1; block_inst.pclk == pclk; endproperty property block_connection_check12; block_inst.pslverr == pslverr; endproperty endclocking block_connection_check1_assert : assert property(cb.block_connection_check1); block_connection_check1_cover : cover property(cb.block_connection_check1); block_connection_check12_assert : assert property(cb.block_connection_check12); endmodule
Conclusion – In summary, the use of IDS-Integrate significantly enhances the verification process for complex ASIC designs. IDS-Integrate simplifies connectivity validation by automatically generating assertions that verify the correct routing and behaviour of signals between various blocks in an SoC design.
These tools streamline the verification workflow, improving design reliability and efficiency by detecting issues early and automating complex checks.
Support for Buffer Trigger Register
Pavneet
Introduction
A Buffer Trigger Register is a specialised type of register used to temporarily hold data before it is processed or transferred to its next destination. The “trigger” aspect of the register refers to a specific event or condition that activates the data transfer or processing. This mechanism ensures that data is handled in a controlled and timely manner, preventing data loss or corruption.
Key Functions of Buffer Trigger Registers
- Data Synchronisation: BTRs are essential in synchronising data between different parts of a system. In systems where components operate at different clock speeds, BTRs help align data transfer timings, ensuring smooth and accurate data flow.
- Buffering: Buffering involves storing data temporarily to manage differences in data rate between the source and the destination. BTRs provide a buffer space that accommodates these rate differences, preventing data overflow or underflow.
- Triggering Mechanism: The triggering mechanism is the core feature of BTRs. Triggers can be based on various conditions, such as reaching a specific count, detecting a particular signal, or fulfilling a predefined condition. When the trigger condition is met, the BTR initiates the transfer or processing of the stored data.
How power optimization works
The operation of a BTR involves several key steps:
- Data Storage:Data is written into the BTR from a source, such as a memory location or an input device.
- Condition Monitoring:The BTR continuously monitors the predefined trigger conditions.
- Trigger Activation:When the trigger condition is met, the BTR activates the data transfer or processing.
- Data Transfer/Processing:The stored data is transferred to the next stage of the system or processed according to the system’s requirements.
- Reset/Reload:After the data transfer, the BTR may be reset or reloaded with new data, ready for the next operation cycle.
IDS support of Buffer Trigger Register
Sometimes it is required that a register with size greater than the bus width is written and read as one atomic unit from the hardware side. Such a register is written/read sequentially from the software side. This can be achieved by creating an N-register buffer in the memory space which is associated with a trigger event. When the trigger event occurs, the write/read happens to/from the buffer to the actual register that is available to the hardware side.
The trigger event can be a read/write to either the Least Significant or the Most Significant register.
A typical design flow is visually depicted in the diagram below:
Since SystemRDL does not support such a register natively. Agnisys® has added a UDP (user defined property) that enables users to describe such a register in SystemRDL.
In SystemRDL such a triggered buffer register is implemented by a reg with the additional property of buffer_trig_reg.
Example
Let’s take a look at an SystemRDL example to understand this. Consider the following input
property buffer_trig_reg {type = string;component = field;}; signal {}S1; addrmap Block1 { reg original_csr{ buffer_trig_reg = "S1:w"; regwidth=32; field { hw = r; sw = rw; }F2[31:16] = 16'h0; field { hw = r; sw = rw; }F1[15:0] = 16'h0; }; original_csr original_csr; };
Verilog Output:
module Block1_ids#(
// PARAMETERS ) ( //Signals : SIGNALS input S1, // REGISTER : ORIGINAL_CSR PORT SIGNAL output original_csr_enb, // REGISTER ENABLE output [15 : 0] original_csr_F1_r, output [15 : 0] original_csr_F2_r, // BUFFER : original_csr_BUFF_0 SIGNALS reg [31:0] original_csr_buff_0; wire [64 - 1 : 0] original_csr_buff_0_offset; wire original_csr_buff_0_wr_valid; wire original_csr_buff_0_decode; wire [31:0] original_csr_buff_0_rd_data;// READ DATA FOR BUFFER //-------------------------------------------------------- // Buffer : original_csr_buff_0 // WIDTH : 32 // SW ACCESS : Read-Write //
assign original_csr_buff_0_wr_valid = original_csr_buff_0_decode && wr_stb; assign original_csr_buff_0_offset = original_csr_offset + 'h0; assign original_csr_buff_0_decode = (address[addr_width-1 :0] == original_csr_buff_0_offset) ? 1'b1 : 1'b0; always @(posedge clk) begin if (!reset_l) begin original_csr_buff_0 <= 32'd0; end else begin if(original_csr_buff_0_wr_valid) // SW Write begin original_csr_buff_0 <= ( wr_data[31:0] & reg_enb[31:0] ) | (original_csr_buff_0 & (~reg_enb[31:0])); end end end // always Buffer clk assign original_csr_buff_0_rd_data = original_csr_buff_0_decode ? original_csr_buff_0 : 32'b0; //------------------------------------------------------------------------- // REGISTER : ORIGINAL_CSR // ADDRESS : block_offset +'h0 WIDTH : 32 // HW ACCESS : RO // SW ACCESS : READ-WRITE // // FIELDS : // 15:0 : F1 ( SW : RW HW : RO ) // 31:16 : F2 ( SW : RW HW : RO ) assign original_csr_wr_valid = original_csr_decode && wr_stb ; assign original_csr_offset = block_offset +'h0; assign original_csr_decode = (address[addr_width-1 : 0] == original_csr_offset[addr_width-1 : 0]) ? 1'b1 : 1'b0; assign original_csr_rd_valid = original_csr_decode && rd_stb ; assign original_csr_enb = original_csr_wr_valid;
// FIELD : F1 // HW ACCESS : RO WIDTH : 16 // SW ACCESS : RW OFFSET : 0 always @(posedge clk) begin if (!reset_l) begin original_csr_F1_q <= 16'd0; end else begin if (S1) //F1 : SW Write begin original_csr_F1_q <= ( original_csr_buff_0[15:0]); end end end //end always assign original_csr_F1_r = original_csr_F1_q; // Field : F1 // FIELD : F2 // HW ACCESS : RO WIDTH : 16 // SW ACCESS : RW OFFSET : 16
always @(posedge clk) begin if (!reset_l) begin original_csr_F2_q <= 16'd0; end else begin if (S1) //F2 : SW Write begin original_csr_F2_q <= ( original_csr_buff_0[31:16]); end end end //end always assign original_csr_F2_r = original_csr_F2_q; // Field : F2 assign original_csr_rd_data = original_csr_buff_0_rd_data;
Importance of Buffer Trigger Registers
- Improved Data Integrity: By ensuring that data is transferred or processed only when specific conditions are met, BTRs help maintain data integrity.
- Efficient Data Management: BTRs provide a structured way to handle data buffering and transfer, improving overall system efficiency.
- Flexibility: The ability to set various trigger conditions makes BTRs adaptable to a wide range of applications and requirements.
Conclusion
Buffer Trigger Registers are vital components in modern digital systems, offering precise control over data buffering and transfer processes. Their ability to manage data synchronisation, handle varying data rates, and initiate actions based on specific triggers makes them indispensable in applications ranging from signal processing to microprocessor operations. As technology continues to evolve, the role of BTRs in ensuring efficient and reliable data management will remain crucial, driving advancements in electronic systems and communication technologies.
Tunable Flow in C Output Format
Mohit Saxena
Introduction
In chip designing, tunability refers to the ability to adjust certain parameters or characteristics of a chip dynamically or through configuration settings. This capability allows for customization and optimization of the chip’s performance according to specific requirements or changing conditions. Tunability can be implemented in various ways depending on the design and intended application of the chip.
Tunables can be used in chip designs in various scenarios depending on the specific requirements of their applications. Here are some situations where tunable chips would be particularly beneficial:
1. Customised Hardware Acceleration
2. Adaptive Systems
3. Energy Efficiency
4. Real-Time Optimization
5. Fault Tolerance and Reliability
For example, IDS supports capturing the desired tunability through user defined properties such as treset, tdesc, tphase and tseq to adjust the register default reset value without changing the hardware properties and functionality during post silicon validation.
Here,
treset: Indicates the default value that should be applied on the field at boot time. Users can apply treset values either in binary, decimal, hexadecimal or octal.
tphase: Indicates the phase in which the treset shall be applied at boot time. If it is not specified then it is considered as “Default”.
tdesc: Indicates the description updated for the tunable fields.
tseq: Indicates the sequence of the registers. In the phase.h file (which will be generated in the output directory), each register should be displayed according to its sequence value. If no sequence value is assigned to a register or if multiple registers have the same sequence value, then the registers should be displayed according to their corresponding addresses.
Now tunables are fully compatible with HTML output. In this newsletter, we’ll introduce tunable support to C-header output format.
C Header files are generated by IDS for the purpose of inclusion in C/C++ code. These header files enable engineers to get access to names, locations and various properties of the registers and bit fields.
Use Cases:
SystemRDL Example:
property chip {type=boolean; component=addrmap;}; property cheader_udstruct {type=boolean; component=addrmap;}; property tdesc {type=string; component=reg;}; property tseq {type=longint unsigned; component=reg;}; property tphase {type=string; component=reg;}; property treset {type=longint unsigned; component=field;}; addrmap top{ Cheader_udstruct = true; reg { tphase = "PHASE1"; tseq = 2; field {}f1; }regA; reg { tseq = 1; tphase = "PHASE1"; field {}f1; }regB; reg { tseq = 1; tphase = "PHASE2"; field {}f1; }regC; reg { tseq = 1; field {}f1; }regD; };
Generated Header:
Now, for header output, “const struct” is used to declare a constant structure variable whose values cannot be modified.
IDesignSpec created separate files for each phase. Now this file contains a list of registers where we have applied a tunable property in the file. The order of registers should be based on seq.
Output Dir Structure:
Output:
Tunable.h
#ifndef TUNABLE_REGISTER_H #define TUNABLE_REGISTER_H #include <stdint.h> struct TunableRegister { uint64_t address; // Register address uint64_t value; // Register value uint64_t reg_size; // Register size in bytes: 1, 2, 4 or 8 }; #endif
The TunableRegister structure is defined in the Tunable.h file and is used to encapsulate information about a register that can be tuned in different phases. This structure consists of three members:
a) Address: uint64_t can support 64-bit wide register value: Should be actual address of the register
b) value: This member holds the actual data stored in the register. is calculated based on the treset values of all fields within the register. If a field does not have a treset value, the reset value of that field should be used for the calculation.
c) reg_size: This is an unsigned int indicating the size of the register in bytes. This member specifies how many bytes the register occupies and can be one of the following values: 1, 2, 4, or 8.
Default_Tunable.h
#include "Tunable.h" const struct TunableRegister Default_Tunable[] = { { .address = 0x0C, /*top.regD*/ .value = 0x0, .reg_size = 4, }, };
PHASE1: #include "Tunable.h" const struct TunableRegister PHASE1_Tunable[] = { { .address = 0x04, /*top.regB*/ .value = 0x0, .reg_size = 4, }, { .address = 0x00, /*top.regA*/ .value = 0x0, .reg_size = 4, }, }; PHASE2: #include "Tunable.h"
const struct TunableRegister PHASE2_Tunable[] = { { .address = 0x08, /*top.regC*/ .value = 0x0, .reg_size = 4, }, };
Conclusion:
To conclude, tunability in chip design allows for dynamic adjustment of key parameters, improving adaptability, energy efficiency, and performance. The use of tunable properties such as treset, tphase, tdesc, and tseq enables control over register configurations during post-silicon validation without altering hardware. IDS extends this support to C header files with the cheader_udstruct property, generating phase-specific files that align registers based on the tseq property. The TunableRegister structure encapsulates address, value, and size, allowing precise control of tunable registers, optimising performance while ensuring compatibility with both HTML and C header outputs.
Concise URL in HTML Output
Gitanjali Singh
Introduction
HTML documentation with clear, concise hyperlinks (URLs) to various registers within a specification is useful. While accessing the HTML documentation, users should be able to click on a link and receive reliable, up-to-date register information. However, previous URLs in the documentation tend to be overly long.
For example, the following URL from the HTML output is very long:
Here, the above URL contains information of GET parameters (e.g., baseA=0x10B00000) which determine the address displayed on the register page. If the register block is moved, for example, to 0x20B00000 address and the documentation link is not updated, in case users click on the link(URL) incorrect address will be shown. This issue persists even with the latest symlink, which means all register links must be manually updated each time there is a change.
Current Flow and JavaScript Logic:
In the current HTML flow, the property doc_repeat_compact is supported, which creates a compact HTML structure. For example, if the addrmap has a repeat count of 500, instead of creating 500 files, a single file is created. From this source HTML file, 500 links are created, each containing details of its instance and hierarchy as query parameters of the link.
It looks like the following:
block.html?bName=block[1]&bAddress=0x500...... block.html?bName=block[2]&bAddress=0x500..... block.html?bName=block[3]&bAddress=0x500..... block.html?bName=block[4]&bAddress=0x500..... ...and so on
The JavaScript logic dynamically calculates the behavior of each link and reflects any changes directly on the HTML page. Because links do not exist (as the data is dynamically generated), the browser must rely on the JavaScript logic to handle the redirection.
Use Cases:
The current lengthy URL structure for accessing the DDR Logic CSR page includes many GET parameters, each specifying a different address or hierarchical component. By replacing these long URLs with shortened versions (e.g., via TinyURL), we can simplify the access process while maintaining the flexibility needed for dynamic URL management.
SystemRDL Example:
property chip {type=boolean; component=addrmap;}; addrmap block1{ regfile { regfile { reg { field {}f1; }regA[5]; }rf2; reg { field {}f1; }regB[3]; }rf1; }; addrmap top{ chip = true; block1 blk1; }; addrmap chip{ chip=true; top top; }; Command: - test.rdl -output "htmlalt2" -top_property "top_display_name=true" -preserve_names -if
Generated Output:
Link – local_path/test_index.htm?top_chip1/top_chip/top/mipa/XYZ_1/REGA
Conclusion:
By transitioning from overly lengthy URLs to more concise formats, we significantly enhance the user experience. These shorter URLs make the documentation not only easier to navigate but also more manageable for updates and maintenance. The new URL structure streamlines access to register information, allowing users to quickly find what they need without the hassle of long, complex links. This improvement reflects our commitment to creating a more efficient and user-friendly documentation system.
Automated VHDL Code Generation
Ashutosh Kumar
VHDL (VHSIC Hardware Description Language) plays a crucial role in the design and verification of digital systems such as FPGAs and ASICs. Engineers use VHDL to describe the behavior, structure and timing of these systems, ensuring that they function as intended before moving to physical implementation. However, manually writing VHDL code can be a challenging and time-consuming task, particularly when dealing with complex designs and stringent deadlines. This is where automation plays an important role.
The Need for Automated VHDL Code Generation
As digital designs become more complex, the traditional manual approach to writing VHDL code often struggles to keep up. Engineers face increasing pressure to deliver designs quickly while maintaining high standards of quality and accuracy. The manual coding process is not only slow but also prone to human error, which can lead to costly rework and delays.
Automated tools for VHDL code generation have emerged as a solution to these challenges. By automating repetitive and error-prone tasks, these tools allow engineers to focus on higher-level design activities, thereby improving both productivity and quality.
Agnisys: Pioneering VHDL Automation
Agnisys has developed a suite of innovative tools that simplify and accelerate the process of VHDL code generation. IDesignSpec tools are designed to seamlessly convert inputs from familiar formats such as Word documents and Excel spreadsheets into accurate and optimized VHDL code. This capability allows engineers to leverage their existing documentation and design data, reducing the time and effort required to create VHDL code from scratch.
One of the key strengths of Agnisys Solution Suite is their user-friendly interface, which simplifies the process of inputting design specifications. Engineers can define registers, memory maps, register sequences and other design elements in Word or Excel, and the tools will automatically generate the corresponding VHDL code. This not only accelerates the design process but also ensures consistency and accuracy in the generated code.
Advantages of Automating VHDL Code Generation.
Increased Accuracy: Automated tools eliminate the risk of human error in VHDL code, resulting in more reliable designs. The precision of automated code generation ensures that the output adheres to the design specifications, reducing the need for costly debugging and revisions.
Faster Development: Automation significantly reduces the time required to generate VHDL code, enabling engineers to meet tight project deadlines without compromising on quality. The time saved can be redirected to more critical tasks, such as design optimization and validation.
Consistency: Automated tools ensure that the generated VHDL code is consistent across different parts of the design, reducing the chances of discrepancies and integration issues. This consistency is particularly important in large, complex projects where multiple engineers may be working on different sections of the design.
Ease of Use: By allowing engineers to use familiar input formats like Word and Excel, Agnisys tools make the VHDL generation process more intuitive and accessible. This ease of use is especially beneficial for teams with varying levels of VHDL expertise.
Enhanced Productivity: With automated VHDL generation, engineers can focus on higher-level design challenges rather than getting bogged down by manual coding. This leads to more innovative and efficient designs, ultimately contributing to the success of the project.
Transforming VHDL Design with Agnisys
Agnisys’ new VHDL generator is designed to be fast, efficient, and reliable, offering a range of powerful features to streamline the RTL generation process. It integrates SystemRDL capabilities with Agnisys’ custom User-Defined Properties (UDP), allowing users to create fully customizable RTL outputs tailored to specific design needs. The generator produces VHDL output in the form of records, which improves organization and readability of the code. It also generates optimized VHDL code, ensuring better performance and resource utilization. Additionally, the tool supports automatic generation of testbenches and assertions, provides error-checking mechanisms, and seamlessly integrates with existing design flows. This flexibility makes it ideal for both simple and complex design projects, helping users save time and reduce manual effort.
Agnisys tools represent a significant advancement in the field of digital design, offering engineers a powerful and efficient way to generate VHDL code. By automating the code generation process, these tools not only save time but also enhance the overall quality of the design. Engineers can trust that the VHDL code produced by Agnisys tools is accurate, consistent, and optimized for their specific needs.
In a competitive landscape where time-to-market is critical, the ability to quickly and reliably generate VHDL code is a significant advantage. Agnisys automation tools provide this advantage, enabling engineers to deliver high-quality designs faster and with greater confidence.System RDL I/P: addrmap block1{ reg reg1{ field f1{ hw=rw; sw=rw; }f1[31:0]=0; }; reg1 reg1; };
Command Line to generate VHDL output with IDS-CLI : idsbatch <i/p file name> -output vhdl -bus apb -dir <>
Agnisys GUI input:
Configuration to generate VHDL output :
Output: . . . . . . . . . ---------------------------------------------------------------------------- -- FIELD : f1 -- HW ACCESS : rw WIDTH : 31 -- SW ACCESS : rw ----------------------------------------------------------------- reg1_f1 : process (clk) begin if rising_edge (clk) then if reset_l = '0' then q_reg1_f1 <= default_reg1_f1; else if (reg_in_enb.reg1_f1 = '1') then -- HW write q_reg1_f1 <= reg_in.reg1_f1; else if (wr_valid_reg1 = '1') then -- SW Write q_reg1_f1 <= ( wr_data(31 downto 0) and reg_enb(31 downto 0) ) or ( q_reg1_f1 and (not(reg_enb(31 downto 0))) ); end if; end if; end if;-- reset end if;-- clock edge end process reg1_f1; -- End REG1_F1 process
Conclusion:
Agnisys provides a robust and innovative solution for automatic VHDL code generation, which not only ensures the generation of error-free code but also enhances the overall design workflow. By automating the process, Agnisys reduces the need for manual intervention, thus minimizing human errors and improving code reliability. The tool allows for seamless integration of various design components, making it easier to manage complex projects and ensuring that the output is aligned with project specifications.