Skip to content
VLSI Mentor

sed Part IV · Module 9 · RTL and Filelist Maintenance

Signal, Module, and Define Renaming

Chapter 9.1 edited paths. This edits a language, and that changes everything. Renaming axi_awvalid across a design means axi_awvalid_d and axi_awvalid_q must not change, which needs a word boundary — and the word boundary is spelled one way on GNU sed and another on BSD, with one of those spellings failing silently on the other. So the only check you can trust is a number that comes out the same on every machine. The chapter runs the full procedure on a real RTL tree and then compiles it, because a claim about a hardware language deserves a compiler as its witness rather than a careful-sounding paragraph.

Advanced21 min readsedPart IVRTLRenamingPortability

Part IV · Module 9 · Chapter 9.2 · Signal, Module, and Define Renaming

1. The Design

A small tree, built so that every way a rename can go wrong is present:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cat -n rtl/alu.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
     1	`include "defs.svh"
     2	module alu (
     3	    input  logic        clk,
     4	    input  logic        axi_awvalid,
     5	    output logic        axi_awready,
     6	    input  logic [31:0] axi_awaddr
     7	);
     8	  logic axi_awvalid_d;   // pipelined copy of axi_awvalid
     9	  logic axi_awvalid_q;
    10	  always_ff @(posedge clk) axi_awvalid_d <= axi_awvalid;
    11	  assign axi_awready = ~axi_awvalid_q;
    12	endmodule

The job: rename the port axi_awvalid to m_axi_awvalid. Lines 4 and 10 must change. Lines 8 and 9 declare different signals — the pipelined copies — and must not.

2. The Procedure

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   1. AUDIT      what names exist, and which share a prefix?
   2. COUNT      how many lines should change?
   3. DRY RUN    the word-boundary rename, both spellings
   4. APPLY      over a file list you have read
   5. COMPILE    the only real proof

3. Step 1 — Audit the Names

Start with what is in the tree rather than what you remember. The registered audit lists every module name:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -n -E 's/^[[:space:]]*module[[:space:]]+([a-z_][a-z0-9_]*).*/\1/p' rtl/*.sv | sort -u
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alu
fifo
macro_user

Three modules. Now the identifier you are about to rename — and specifically, what else starts with it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -oh 'axi_awvalid[a-z_0-9]*' rtl/*.sv | sort -u
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
axi_awvalid
axi_awvalid_d
axi_awvalid_q

Three distinct identifiers share the prefix. That single command is the whole problem, discovered before anything is written. A naive s/axi_awvalid/m_axi_awvalid/g would rename all three, and _d and _q are different signals.

And which files are involved:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -rc 'axi_awvalid' rtl/ | grep -v ':0$'
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rtl/fifo.sv:3
rtl/macro_user.sv:1
rtl/alu.sv:5
rtl/defs.svh:1

Four files, and note the fourth: defs.svh. Keep that in mind for section 6.

4. Step 2 and 3 — Count and Dry Run

The naive version, on alu.sv alone:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -n 's/axi_awvalid/m_axi_awvalid/gp' rtl/alu.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    input  logic        m_axi_awvalid,
  logic m_axi_awvalid_d;   // pipelined copy of m_axi_awvalid
  logic m_axi_awvalid_q;
  always_ff @(posedge clk) m_axi_awvalid_d <= m_axi_awvalid;
  assign axi_awready = ~m_axi_awvalid_q;

Five lines. m_axi_awvalid_d and m_axi_awvalid_q are signals that do not exist.

The word-boundary version, in the BSD/macOS spelling:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -n 's/[[:<:]]axi_awvalid[[:>:]]/m_axi_awvalid/gp' rtl/alu.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
    input  logic        m_axi_awvalid,
  logic axi_awvalid_d;   // pipelined copy of m_axi_awvalid
  always_ff @(posedge clk) axi_awvalid_d <= m_axi_awvalid;

Three lines, and the declarations of _d and _q are intact. Line 9 is absent from the output entirely because nothing on it changed.

As counts:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -n 's/axi_awvalid/&/gp' rtl/alu.sv | wc -l
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
       5
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -n 's/[[:<:]]axi_awvalid[[:>:]]/&/gp' rtl/alu.sv | wc -l
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
       3

Five versus three. The replacement is & in both, so these commands measure without editing — Chapter 7.3's trick.

5. Step 4 — Apply Across the Tree

The file list comes from the audit, not from a glob you typed from memory. Chapter 8.3's rules apply: read the list, then use it.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   grep -rl --null 'axi_awvalid' rtl/ | xargs -0 -n1 echo     read it first
   grep -rl --null 'axi_awvalid' rtl/ | xargs -0 \
       sed -i '' 's/[[:<:]]axi_awvalid[[:>:]]/m_axi_awvalid/g'

Write --null in full — Chapter 8.3 measured -Z meaning something else entirely on two of the three greps available. And -i '' is the BSD spelling from Chapter 7.1.

Commit before this, per Chapter 7.2. The next section is why that matters more here than anywhere else in the track.

6. Step 5 — Compile, Because Nothing Else Is Proof

Every other chapter in this track proves its claims with sed's own output. Here the claim is about a hardware language, so the witness has to be a compiler.

Baseline — all three modules build before anything is touched:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
iverilog -g2012 -I work -o /tmp/alu.out  work/alu.sv
iverilog -g2012 -I work -o /tmp/fifo.out work/fifo.sv
iverilog -g2012 -I work -o /tmp/mu.out   work/macro_user.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet

Three commands, no output, exit 0 each. Now apply the correct word-boundary rename to the SystemVerilog sources:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -i '' 's/[[:<:]]axi_awvalid[[:>:]]/m_axi_awvalid/g' work/*.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet

Exit 0. The rename is right, the boundaries held, _d and _q are untouched. Compile again:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
iverilog -g2012 -I work -o /tmp/mu.out work/macro_user.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
work/macro_user.sv:3: error: Unable to bind wire/reg/memory `axi_awvalid' in `macro_user'
work/macro_user.sv:3: error: Unable to elaborate r-value: axi_awvalid
2 error(s) during elaboration.

Exit status 2. The build is broken, by a rename that was correct in every way this chapter has described so far.

Look at what happened:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cat -n work/macro_user.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
     1	`include "defs.svh"
     2	module macro_user (input logic clk, input logic m_axi_awvalid);
     3	  wire v = `AXI_VLD;
     4	endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cat -n work/defs.svh
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
     1	`define AXI_VLD axi_awvalid
     2	`define DBG 1

The port was renamed. The macro still expands to the old name, so line 3 references a signal that no longer exists.

Two independent causes, and both are worth separating:

  1. The glob missed the file. work/*.sv does not match defs.svh. Section 3's audit listed four files containing the name and this was the fourth.
  2. The identifier is reached through a macro. Even with the file included, AXI_VLD is a name for a name — sed sees two unrelated strings where the compiler sees one signal.

The first is fixable here. Include the header:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sed -i '' 's/[[:<:]]axi_awvalid[[:>:]]/m_axi_awvalid/g' work/defs.svh
cat -n work/defs.svh
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
     1	`define AXI_VLD m_axi_awvalid
     2	`define DBG 1
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
iverilog -g2012 -I work -o /tmp/mu.out work/macro_user.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet

Exit 0. Fixed.

7. The Audit That Would Have Prevented It

Section 3 already had the answer, which is the point of doing it first:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -rl 'axi_awvalid' rtl/ | sort
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rtl/alu.sv
rtl/defs.svh
rtl/fifo.sv
rtl/macro_user.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls rtl/*.sv
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rtl/alu.sv
rtl/fifo.sv
rtl/macro_user.sv

Four files contain the name; *.sv matches three. The discrepancy is visible in two commands, before any edit, and it is the whole bug.

The general rule: derive the file list from the content, not from an extension. grep -rl --null 'name' rtl/ finds every file that mentions the identifier regardless of what it is called — .sv, .svh, .v, .vh, a filelist, a constraint file, a README. A glob encodes an assumption about naming; a content search does not.

8. Renaming a Module or a Define

The same procedure, with two differences worth stating.

A module name appears in its declaration and at every instantiation, and the instantiation looks nothing like the declaration:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
   module alu ( … );          the declaration
     alu u_alu ( … );         an instantiation — the name is first on the line

Both are caught by a word-boundary rename, but the audit matters more because an instance may live in a file that has no other reference to the module. Section 3's grep -rl is again the right list.

A define name has an extra hazard: the definition and the uses are in different files by design, and the uses are written with a backtick. `AXI_VLD and AXI_VLD are the same macro, so a pattern anchored on the backtick will miss the definition and a pattern without it will match both — which is usually what you want, and worth checking rather than assuming.

What neither of these changes is the ceiling. A rename that sed performs correctly can still be wrong, because the text it matched does not always mean what you think.

9. Think It Through

1. What single command tells you a naive rename is unsafe, before you run it?

grep -oh 'name[a-z_0-9]*' rtl/*.sv | sort -u. If it returns more than one line, other identifiers share your prefix and a plain substitution will catch them. Section 3 returned three.

2. Your rename script works on Linux and renames nothing on a Mac, exit 0. Why?

It uses GNU's \b, which BSD sed does not implement as a word boundary — section 4 measured zero lines changed, exit 0. Use the detection branch, and assert the expected count so a zero is a failure rather than a silent success.

3. The rename exits 0 and the build fails with "Unable to bind". What are the two things to check?

Which files were in the list, and whether the identifier is reached through a macro. Section 6 hit both at once: *.sv missed defs.svh, and that header defines a macro expanding to the old name. grep -rl versus your glob is the first check; grep -rn 'define.*name'` is the second.

4. Why derive the file list from grep -rl rather than from *.sv?

Because a glob encodes a guess about file extensions and the content search does not. Section 7 measured four files containing the identifier where *.sv matched three. The missing one was a header, and it broke the build.

5. You rename a module. What is different from renaming a signal?

The uses are instantiations, which may sit in files that mention the module nowhere else — so the audit matters more, and grep -rl is the only reliable way to find them. The substitution itself is the same word-boundary rename.

6. The rename compiled cleanly. Is it correct?

Not necessarily. A compile proves the design still elaborates; it does not prove you renamed the right things. This chapter's own fixture has a rename that compiles and is wrong — the identifier inside a $display string, which changes what the simulation prints without changing what it does. That is Chapter 9.3, and it is the reason this module has a third chapter.

10. Summary

  • Audit before you edit. grep -oh 'name[a-z_0-9]*' | sort -u returned three identifiers sharing the prefix — the problem, found in one command.
  • A rename needs a word boundary. Naive: 5 lines changed on alu.sv. Word-boundary: 3. Measured with & as the replacement, so neither command edited anything.
  • The spellings are not portable. [[:<:]]/[[:>:]] work on BSD; GNU's \b changed 0 lines and exited 0 here. Branch on sed --version, and assert the count.
  • Derive the file list from content, not from a glob. Four files contained the identifier; *.sv matched three.
  • Compile as step 5. Baseline exit 0; after a correct-looking rename, iverilog gave Unable to bind wire/reg/memory 'axi_awvalid', exit 2 — because the glob missed defs.svh and the signal is reached through a macro.
  • Renaming the header too restored exit 0, but only because the macro happened to be a simple alias.
  • A module rename is the same procedure with a stronger need for the audit, since instantiations hide in unrelated files.
  • A clean compile is not a correct rename. It proves elaboration, not intent.

The compile caught the macro. It did not catch the comment this rename rewrote, or the string inside $display that now prints a signal name the design no longer uses — both compile perfectly. Chapter 9.3 — Safe RTL Refactoring Boundaries is about exactly those: what text substitution cannot know, which renames therefore need a syntax-aware tool, and how to tell the difference before you start.

Where this fits

Part of the sed curriculum.