Verilog: Common bus implementation issue - verilog

I've been coding a 16-bit RISC microprocessor in Verilog, and I've hit yet another hurdle. After the code writing task was over, I tried to synthesize it. Found a couple of accidental mistakes and I fixed them. Then boom, massive error.
The design comprises of four 16-bit common buses. For some reason, I'm getting a multiple driver error for these buses from the synthesis tool.
The architecture of the computer is inspired by and is almost exactly the same as the Magic-1 by Bill Buzzbee, excluding the Page Table mechanism. Here's Bill's schematics PDF: Click Here. Scroll down to page 7 for the architecture.
The control matrix is responsible for handling when the buses and driven, and I am absolutely sure that there is only one driver for each bus at any given instance. I was wondering whether this could be the problem, since the synthesis tool probably doesn't know this.
Tri-state statements enable writing to a bus, for example:
assign io [width-1:0] = (re)?rd_out [width-1:0]:0; // Assign IO Port the value of memory at address add if re is true.
EDIT: I forgot to mention, the io port is bidirectional (inout) and is simply connected to the bus. This piece of code is from the RAM, single port. All other registers other than the RAM have separate input and output ports.
The control matrix updates a 30-bit state every negative edge, for example:
state [29:0] <= 30'b100000000010000000000000100000; // Initiate RAM Read, Read ALU, Write PC, Update Instruction Register (ins_reg).
The control matrix is rather small, since I only coded one instruction to test out the design before I spent time on coding the rest.
Unfortunately, it's illogical to copy-paste the entire code over here.
I've been pondering over this for quite a few days now, and pointing me over to the right direction would be much appreciated.

When re is low, the assign statement should be floating (driving Zs).
// enable ? driving : floating
assign io [width-1:0] = (re) ? rd_out [width-1:0] : {width{1'bz}};
If it is driving any other value then the synthesizer will treat is as a mux and not a tri-state. This is where the conflicting driver message come from.

Related

Error: driven via a port connection, is multiply driven

I am able to build the code in modelsim but, when simulation getting below error:
addr_x, driven via port connection, is multiply driven (44) Line :49
addr_f, driven via port connection, is multiply driven (46) Line :49
s_ready_x, driven via port connection, is multiply driven (44) Line :49
s_ready_f, driven via port connection, is multiply driven (46) Line :49
How can I resolve this? (system verilog)
There is no simple* fix: You have to change your design. You might even have to go "back to the drawing board" and fundamentally change your design.
In each of the ctrlpath.., modules you output an address. Thus you drive the same net from different outputs. You somehow have to distinguish which of those you are really going to need. Thus you need to add a multiplexer which 'knows' which on to pick.
The "multiple driven" error is a recurring question appearing on Stack Overflow and Electrical engineering. What you have done is connecting multiple output ports together. In electrical engineering we call this 'shorting outputs together'. The term shorting is important as it is effectively a short circuit. This is the equivalent circuit:
Some outputs will be high and others are low. The ones which are high will try to drive the output high opening a current path from the VCC to the output pin. The ones which are low will try to drive the output low. They open a current path from the output to ground. Together they form a short circuit between your VCC and ground.
*Do not think you can easily solve this with tri-state drivers. Theoretical it may seem possible, practically you really, really don't want that.
Here is one of the messages from VCS compilation:
Error-[ICSD] Illegal combination of drivers
design.sv, 38
Illegal combination of structural drivers.
Variable "s_ready_x" is driven by multiple structural drivers.
This variable is declared at
"design.sv", 38: logic s_ready_x;
The first driver is at "design.sv", 50: ctrlpatho c( .clk (clk), .reset
(reset), .wr_done_f (wr_done_f), .wr_done_x (wr_done_x), .addr_x
(addr_x), .addr_f (addr_f), .m_valid_y (m_valid_y), .c ...
The second driver is at "design.sv", 45: ctrlpathx x( .clk (clk), .reset
(reset), .s_ready_x (s_ready_x), .addr_x (addr_x), .wr_done_x
(wr_done_x), .wr_en_x (wr_en_x), .s_valid_x (s_valid_x));
it just propagates the issue to the top-level module, but gives correct locations of the drivers.
The problem is, that both ctrlpathf and ctrlpatho drive the same signal with output ports. The rule of thumb is:
you cannot drive the same variable with multiple drivers.
System verilog just adds this requirement to the standard and it gets checked for the specific system verilog blocks.
To fix it
you need to review your program, in case you just made a mistake.
verilog allows you to multiply drive net types and defines rules for the results. If you really want to have multiple drivers, you would need to declare those ports as wires or similar and change the code to reflect it. They can be multiply driven with the assign statements.

How to set a signal high X-time before rising edge of clock cycle?

I have a signal that checks if the data is available in memory block and does some computation/logic (Which is irrelevant).
I want a signal called "START_SIG" to go high X-time (nanoseconds) before the first rising edge of the clock cycle that is at 10 MHz Frequency. This only goes high if it detects there is data available and does further computation as needed.
Now, how can this be done? Also, I cannot set a delay since this must be RTL Verilog. Therefore, it must be synthensizable on an FPGA (Artix7 Series).
Any suggestions?
I suspect an XY problem, if start sig is produced by logic in the same clock domain as your processing then timing will likely be met without any work on your part (10MHz is dead slow in FPGA terms), but if you really needed to do something like this there are a few ways (But seriously you are doing it wrong!).
FPGA logic is usually synchronous to one or more clocks,generally needing vernier control within a clock period is a sign of doing it wrong.
Use a {PLL/MCM/Whatever} to generate two clocks, one dead slow at 10Mhz, and something much faster, then count the fast one from the previous edge of the 10MHz clock to get your timing.
Use an MCMPLL or such (platform dependent) to generate two 10Mhz clocks with a small phase shift, then gate one of em.
Use a long line of inverter pairs (attribute KEEP (VHDL But verilog will have something similar) will be your friend), calibrate against your known clock periodically (it will drift with temperature, day of the week and sign of the zodiac), this is neat for things like time to digital converters, possibly combined with option two for fine trimming. Shades of ring oscs about this one, but whatever works.

Overriding a clock pin with manual control, then clocking again

An interesting issue arose with a device whose SWD_CLK pin is shared as a 'device boot mode' pin (ROM/Flash boot, etc.). The specification states that the SWD_CLK should be held high for some time before functioning as SWD_CLK.
The origen_swd plugin drives the clock high to 'enable' it, so the timeset for this pin must be 'return low' in order to clock. But, when I try to drive this high and hold it high, it begins clocking. Is there a way to disable the timeset for some time, then re-enable it when ready?
The workaround is to change the origen_swd to accept an option to either drive high or drive low to enable, then change the timeset in my application to return high.
Using metaprogramming to just grab and edit instance variables of the timeset may also be a solution, but is there a supported API to handle the tasks like the above?
Thanks
The way to do this would be by making two timing options for the given pin, one with the return low and one without.
tester.set_timeset "mode_entry", 40
pin(:swd_clk).drive!(1)
# Sometime later once in mode
tester.set_timeset "func_swd", 40
If the tester supports (e.g. V93K) you can also define multiple wave forms for a pin within the same timeset, as shown at the end of this guide section - http://origen-sdk.org/origen/guides/pattern/timing/#Complex_Timing
Then you would just have a single timeset selection and control the wave you want on the pin like this:
pin(:swd_clk).drive!(1) # Would be defined in the timing as always high
pin(:swd_clk).drive!('P') # Now start the clk pulse
Both of these approaches will work in the generated ATE patterns, however at the time of writing I believe that OrigenSim does not yet support the second approach, so you will have to use the multiple timesets.
As an aside, you sound like you are only looking for a solution that works in simulation and not necessarily required to have the two types of waves within the final ATE pattern.
In that case, you could also try poking the testbench's pin driver force data bit, though I haven't tried this:
tester.simulator.poke('origen.pins.swd_clk.force_data[1]', 1);
If you have success with that, we should think about adding a convenience API to do this kind of thing in simulation:
pin(:swd_clk).force!(1)

Using single ended port in logic expecting diff-pair?

The logic that I am using is set up to expect a diff-pair clock port. However, for one specific application, I can only input a single ended clock (due to hardware limitation). Modifying the logic to accept single ended clock is not an option as there are many files and lines of code involved. Is there a way I can input a single ended port and somehow feed it to diff-pair ports of modules? So for example in my top level I want to have a port like this:
input single_ended_clk
And I want to feed this to a module that takes the following ports:
input diff_pair_clk_p;
input diff_pair_clk_n;
A very naïve approach would be to do this:
mymodule m_i (
.diff_pair_clk_p(single_ended_clk),
.diff_pair_clk_n(~single_ended_clk),
);
but I don't think this is the proper way to do this.
Most chip designs, either ASICs or FPGAs explicitly instantiate clock buffers rather than infer them. In the FPGA world, the synthesis engines usually aren't smart enough to recognize a clock and hook the buffer outputs to the dedicated clock routing resources. So you really probably need to explicitly instantiate a clock buffer.
Now as to the case where sometimes you want a single ended clock buffer and sometimes you want a double edge clock buffer. While you can use generate statements referencing a parameter to decide which buffer to instantiate, you can't control the port list of the chip this way. You can keep the clock buffer inside the lower level module.
I would not recommend recreating a differential signal inside the chip. There are several problems with this. First, a differential clock buffer expects to be connected to external pins, not internally buffered signals. Secondly, there is a timing mismatch between the positive and negative clock which could create glitches on your resulting clock post-buffer which would make a real mess of your design.
Instead, keep both _n and _p inputs to your sub-module, and use a generate to select the type of clock buffer to be instantiated. In the case of a single ended clock, the _n input is left unconnected and only the _p input is used.
Here's an example for a Xilinx FPGA. The buffer primatives will be named differently in other types of FPGAs or ASIC libraries.
module clock_buffer (
input pin_clk_p,
input pin_clk_n,
output clk_int
);
parameter DIFF = 0;
generate
if (DIFF = 1)
clk_buf IBUFGDS(
.I (pin_clk_p),
.IB (pin_clk_n),
.O (clk_int)
);
else
clk_buf IBUFG(
.I (pin_clk_p),
.O (clk_int)
);
endgenerate
endmodule
There will be a phase offset, it might be within tolerance. It is hard to say without knowing timing requirements for the differential paired clock and single clock, how the clock tree is being handled, timing of buffers and inverters. You may be able to handle this from within the synthesizer by identifying the clocks and there relation. To do this, assign the clocks individually at the appropriate hierarchy level, maybe its own sub-module. diff_pair_clk_p and single_ended_clk are functionally the same, but they should be separated for load balancing and clock-tree balancing.
assign diff_pair_clk_p = single_ended_clk;
assign diff_pair_clk_n = ~single_ended_clk;
Sometime there are predefined modules that are part of the standard/macro cell library which are intend for solving or simplifying specific design challenges. Instantiate these modules where needed, a dont_touch pragma may be needed. Specifically look for cells described as symmetrical buffers and inverters. You may still need to give additional guidance to the synthesizer.

Verilog Tri-State Issue (Xilinx Spartan 6)

Referring to my earlier question here, I've been utilizing tri-states to work with a common bus. I still appear to have some implementation issues.
The tri-states use this type of code:
assign io [width-1:0] = (re)?rd_out [width-1:0]:{width{1'bz}};
Synthesis and translation goes well. No warnings or errors I wasn't expecting (I was expecting some since this is only a trial run and most of the components don't do anything and will hence be left unconnected). But when I actually try to implement it, all busses (there are three) output a 1111111111111111, or a -1, as converted by my binary to BCD converter. I checked if it really the case by instructing the control matrix to halt if the instruction received on the bus is -1, and it did halt.
The warning I receive for the tri-state being converted to logic is:
Xst:2040 - Unit Neptune_I: 16 multi-source signals are replaced by logic (pull-up yes)
Xst:2042 - Unit alu: 16 internal tristates are replaced by logic (pull-up yes):
And so on. Neptune_I is the top module, and I believe the multi-source signals it's referring to are the busses.
I have a doubt whether the pull-up yes is the root of this problem. Is it simply pulling everything up, causing it to be -1 all the time? But this does not make sense to me, because when the tri-state is activated, the signal should be controlled by whatever entity it is supposed to be controlled by.
I would like to take the time to replace the code with logic instead of the tri-states, but I'm unsure how to proceed.
Any help would be appreciated.
Are these signals going off-chip? Or are they internal to your FPGA? If the answer is the latter, you need to change your code. Modern FPGAs (like Spartan 6) no longer support internal tri-state buffers. They only exist for off-chip signals.
You need to write all of you internal code to avoid tri-state buffers. Create dedicated paths between components, no bidirectional interfaces.

Resources