How to use regs to modify wires? - verilog

I am kind of new to Verilog and was wondering how I can modify wires. I know that you cannot modify wires inside always blocks.
I've seen something like this where you can declare some regs and assign the wire to those regs (which you can then modify the reg to modify the wire?)
module something
#(parameter D_W = 8)
(
input wire clk,
input wire rst,
output wire valid,
output wire [D_W-1:0] data,
);
reg valid_rg = 0;
reg [D_W-1:0] data_rg = 0;
assign valid = valid_rg;
assign data = data_rg;
I was wondering how to do something like that for a wire like:
wire [7:0] wire_a [7:0];
Initially my guess would be to have something like this
reg [7:0] wire_a_rg [7:0];
assign wire_a[7:0] = wire_a_rg[7:0];
But I have a feeling it might be wrong. How could I approach this?

There's no need to use wires in SystemVerilog unless you need to model bi-directional buses, or any kind of circuitry with multiple drivers. You can write
module something
#(parameter D_W = 8)
(
input logic clk,
input logic rst,
output logic valid,
output logic [D_W-1:0] data,
);
And then you can make procedural assigmemnts to valid/data in an always block, or a continuous assign statement (but not both).
BTW, SystemVerilog prefers the use of logic keyword over synonym reg.
You should read my post about the difference between nets and variables.

Related

Simple assignment of wire to output led in verilog doesn't synthesis with yosis

The following code will not build exiting with Error Code -6
module and_gate (
input [1:0] io_button,
output [2:0] io_led
);
wire wire1;
assign wire1 = io_button[0];
assign io_led[0] = wire1;
endmodule
But making this small change builds properly. Can you not just assign a wire to an output without modifying it in some way?
module and_gate (
input [1:0] io_button,
output [2:0] io_led
);
wire wire1;
assign wire1 = io_button[0];
assign io_led[0] = ~wire1;
endmodule
I've seen this before. Some synthesis tools don't handle well the case of there being zero gates in the design, as that means there's zero die area needed before routing. I'm guessing the tool is hitting some internal divide-by-0.
So yes, you can simply connect a wire to an output. That by itself is perfectly valid. And you can even connect an input directly to an output. As long as you have any other gates in the design, even unrelated/unconnected to the ports/nets in your example, the synthesizer would be happy, as there'd be non-zero die area.
So I bet this would work fine:
module and_gate (
input [1:0] io_button,
output [2:0] io_led
);
wire wire1;
assign wire1 = io_button[0];
assign io_led[0] = wire1;
assign io_led[1] = ~io_button[1]; // added line, just to infer a gate somewhere
endmodule

Wire with multiple modules

I am trying to simulate a really basic memory model by having multiple memory blocks (initiations of a basic module) and tying the output of all those blocks to one wire. Is this the way to do this?
module memoryBlock(
input Enable,
output [7:0] dataOut,
input [7:0] dataIN
);
always #(*) begin
if(Enable == 1)
dataOut = dataIn;
end
endmodule;
The idea is that only one of these data blocks would be enabled at a time, and then I could pass whatever information was in the enabled block to the output wire. Here is how I would use it:
module testbench;
reg [7:0] exampleData1 = 8'b00000001;
reg [7:0] exampleData2 = 8'b11111111;
reg enable1 = 0;
reg enable2 = 1;
wire [7:0] outputForBoth;
memoryBlock mb1(enable1, outputForBoth, exampleData1);
memoryBlock mb2(enable2, outputForBoth, exampleData2);
endmodule;
When I have tried sample stuff like this before the output has just been 'zzzzzzzz'. My goal is to be able to have multiple memory blocks.. only enable one of them, and have that wire hold whatever data from that block. Is this the correct approach? Any help would be huge!
This way I only have one place I need to go to retrieve all of the output information. The other way I thought to do this was building a MUX of some sorts, and it just seems a lot more complicated that it needs to be!
You need tri-state outputs to do this. Tri-states drive a wire when enabled and are at high impedance state when not. But you need to make sure that you don't enable two modules at the same time.
module memoryBlock(
input enable,
inout [7:0] dataOut,
input [7:0] dataIN
);
assign dataOut = enable? dataIn : 8'bzzzzzzzz;
endmodule

What will the assign statements get synthesized as?

I am interested to know what will these lines synthesize to? I am designing a direct mapped cache and using assign to separate my index, offset and tag bits. Will it synthesize to a demultiplexer? I did not mention the whole code since I just want to know how the assign statements will look after synthesis. In 8085 programming, I had read the term as 'address demultiplexing" so it was confusing.
module cache
( input bit clk,
input bit rst,
input logic [15:0] address,
input logic valid_in,
input logic compare,
input logic wr,
input logic enable,
input logic write_through,
output logic dirty,
output logic [4:0] tag_out,
output logic [15:0] data_out,
output logic valid_out,
output hit
);
logic [7:0] index;
logic [1:0] offset;
logic [4:0] tag_in;
assign offset = address[1:0];
assign index = address[9:2];
assign tag_in = address[15:10];
endmodule
The above code will just simply get synthesized as wire's, since there are only assignments.
I am not sure what de-multiplexing logic you are trying to create, but generally for a de-multiplexer you need to have a select signal based on which you decode which output should be enabled.
An example for a 1:2 de-multiplexer logic is given below
module demux_1_2(
input [3:0] Q,
input Sel,
output reg [3:0] D1,
output reg [3:0] D2
);
always#(*)
begin
if(~Sel) begin
D1 = Q;
D2 = 0;
end else begin
D1 = 0;
D2 = Q;
end
end
endmodule
Since there are no Boolean or arithmetic operators on the RHS of the assign, these statements just become conveniently named references for part selects of the address input. This is the same thing that happens when you instantiate a module and connect to its ports - signals can go through a name change. In fact, you could have you could have written your address input port declaration as
input .address({tag_in,index,offset}),
You still connect the address port when instantiating this module, but inside the module, it only has tag_in, index, and offset available to reference, not address.
SystemVerilog has the alias construct to make it more obvious that you are just creating a convenient names for a signal, instead of declaring another set of signals and using the assign statement.
alias offset = address[1:0];
alias index = address[9:2];
alias tag_in = address[15:10];

Verilog Reg/Wire Confusion

I'm making a Multicycle CPU in Verilog that consists of a Datapath and a Control. The outputs of the control (state machine) are registers, but the connections between the datapath are wires. If a wire signal is supposed to be (in psuedo-code): wire = OR(wire coming from a mux, reg output from control), how do I do this? Can you OR a wire with a reg in Verilog? If not is there a better way to implement this? Can the control signal outputs be registers in the control module, but wires in the top module?
Update with picture for clarification:
Yes, you can or a wire and a reg output in Verilog.
Yes, each sub-module's outputs, which are essentially wires, can be directly or indirectly internally connected to a reg within the sub-module.
I think that is a fine way to do it.
Now, you can even declare the outputs of a module to be "reg", but that is just semantic sugar over declaring the output and reg separately. I like the explicit way better (i.e. q1_o and q1_reg).
module Submod(input clk_i, intput d_i, output q1_o, output reg q2_o);
reg q1_reg;
always #(posedge clk_i) begin
q1_reg <= d_i;
q2_o <= ~d_i;
end
assign q1_o = q1_reg;
endmodule
module Main(input clk_i, input [3:0]ext_i, output [1:0]ext_o)
wire mux, x1, x2;
Submod Submod_inst(clk_i, ext_i[0], x1, x2);
assign ext_o[0] = x1;
assign mux = ext_i[1] ? ext_i[2] : ext_i[3];
assign ext_o[1] = mux | x2; /* something like this */
endmodule

Having trouble with Verilog inout wires

For the record, I'm a complete Verilog newbie. I'm writing a module that uses a few bidirectional buses.
inout wire [KEY_SIZE-1:0] prevKey;
inout wire [TAG_SIZE-1:0] prevTag;
inout wire [KEY_SIZE-1:0] nextKey;
inout wire [TAG_SIZE-1:0] nextTag;
I know how I read things off of the bus, but how do I write something onto it? If I use an assign statement to a reg, will the value of the reg get clobbered when new data comes onto the wire? Is dealing with an inout port worth the hassle, or should I just make an input and and output bus for each?
If I use an assign statement to a reg...
This statement doesn't really make sense, you don't do assignments to regs, you do assignments to wires.
Simple example of driving an inout wire:
inout wire bidir_wire;
reg drive_value;
reg drive_enable;
reg something;
assign bidir_wire = drive_enable ? drive_value : 1'bz;
always #(posedge clk) begin
drive_value <= ... ; //assign a drive value based on some criteria
drive_enable <= ...;
something <= bidir_wire; //do something with the input value
end

Resources