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
Related
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.
I want to use SW[15] to switch between module A_7seg and B_7seg but it does not work. (2 modules work separately)
module mix(input CLOCK,input [15:0]SW,output reg [15:0] led,output [3:0] an,output reg[7:0] seg);
generate
case(SW[15])
1'b0:A_7seg (.CLOCK(CLOCK),.an(an),.seg(seg));
1'b1:B_7seg (.CLOCK(CLOCK),.SW(SW),.led(led),.an(an),.seg(seg));
endcase
endgenerate
endmodule
Since '2 modules work separately', the simple way is to use SW[15] to select between 2 modules' outputs.
module mix(
input CLOCK,
input [15:0] SW,
output reg [15:0] led,
output reg [3:0] an,
output reg [7:0] seg
);
wire [15:0] B_led;
wire [3:0] A_an, B_an;
wire [7:0] A_seg, B_seg;
// if not using 'generate' block, modules are instantiated at
// the top level, not in other 'if'/'case'/... structures.
// and name the 2 instantiations
A_7seg u_A_7seg (.CLOCK(CLOCK), .an(A_an), .seg(A_seg));
B_7seg u_B_7seg (.CLOCK(CLOCK), .SW(SW), .led(B_led), .an(B_an), .seg(B_seg));
// this extra circuit is needed to select between the two
always#(*)begin
if(SW[15])begin
led = B_led;
an = B_an;
seg = B_seg;
end
else begin
led = 16'h0; // <-- I assume the inactive value for 'led' is all-zero
an = A_an;
seg = A_seg;
end
end
endmodule
You may also want to use SW[15] to gate the inputs to the one that is not currently working to reduce power consumption.
You need to figure out the schematic before you understand how to write the code.
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
I am writing a simple system in which there is a memory module (simple reg with a read and write signals). Now this memory has to be accessed by several other modules (not simultaneously). So I create an instance of this memory and feed data to it. But I can't figure out how will my other modules access the same instance of the memory module. Any help?
Edit
Let me clarify a bit by some code. This is my memory module, simple signals.
module rom(
input [15:0] addr,
input [15:0] data_in,
input rd,
input wr,
input cs,
output reg [15:0] data_out
);
reg [15:0] mem[255:0];
integer k;
initial begin
for(k = 0;k<256;k=k+2)
mem[k] = 16'h0011;
for(k = 1;k<256;k=k+2)
mem[k] = 16'h0101;
end
always #(cs)begin
if(wr)
mem[addr] <= data_in;
if(rd)
data_out <= mem[addr];
end
endmodule
This will be instantiated in my top module, something like this
module Top;
// Inputs
reg [15:0] addr;
reg [15:0] data_in;
reg rd;
reg wr;
reg cs;
// Outputs
wire [15:0] data_out;
// Instantiate the Unit Under Test (UUT)
rom uut (
.addr(addr),
.data_in(data_in),
.rd(rd),
.wr(wr),
.cs(cs),
.data_out(data_out)
);
....
....
....
endmodule
Now this top module will also contain some other modules which would want to connect to memory. I don't really understand how I would connect them. Suppose there is one module like this
module IF_stage(
input clk,
input rst,
output reg [15:0] pc,
output [15:0] instruction
);
//pc control
always#(posedge clk or posedge rst)
begin
if(rst)
pc <= 16'hFFFF;
else
pc <= pc+1;
end
....
How would I access the memory module from here?
Answering your comment, you don't instance the memory more than once. You create one instance of the memory at some level of the hierarchy, and then connect all the consumers to it via ports/wires. So in the top level you might have 3 modules that want to access memory, and 1 memory module. The three accessors each connect to the single instance, they don't instance their own memory.
The memory should be parallel to the other modules, not inside of them, if that makes sense.
You need to modify IF_stage to add an interface that can communicate with the memory, something like this:
module IF_stage(
input clk,
input rst,
input [15:0] read_data_from_memory, //new
input read_data_from_memory_valid, //new
output reg [15:0] pc,
output [15:0] instruction
output do_memory_write //new
output do_memory_read //new
output [15:0] memory_write_data //new
output [15:0] addr //new
);
Then when an IF_stage wants to read or write memory, it puts addr/data on it's output port to issue command to the memory module, and then waits for read_data_from_memory(_valid) to be asserted on it's input port. These outputs and inputs get connected to the memory module at the top level.
You'll also have to deal with bus contention here, for instance if two instances of IF_stage try to read/write at the same time, you'll need some kind of arbiter module to acknowledge both requests, and then forward them one at a time to the memory, and return the valid data to the proper module.
First of all, the name of your memory is "rom", which is read only. I assume it is a typo, otherwise there is no need to have wr port and you can simply implement separate roms in clients and let synthesizer to optimize the design.
For your question, basically you need an arbiter to handle the contention between multiple clients. All clients can assume they occupy the memory exclusively but the memory is shared by all clients and cannot be accessed simultaneously.
Tim is right about the IF_stage. Every client must have a separate memory interface
output [15:0] addr;
output [15:0] data_out;
input [15:0] data_in;
output wr, rd, cs;
input rdy; // only when rdy == 1, the memory operation is finished
You will need a memory controller/arbiter, which behaves as a memory to all clients but actually handle the contention among clients. Assuming there are three clients and all clients access the memory less than once per three cycles, you can simply have something as follow:
module mem_ctl(
addr_c1, dw_c1, dr_c1, wr_c1, rd_c1, cs_c1,
addr_c2, dw_c2, dr_c2, wr_c2, rd_c2, cs_c2,
addr_c3, dw_c3, dr_c3, wr_c3, rd_c3, cs_c3,
addr_m, dw_m, dr_m, wr_m, rd_m, cs_m,
rdy_c1, rdy_c2, rdy_c3,
rst_n, clk
);
input clk, rst_n;
input [15:0] addr_c1, addr_c2, addr_c3, dw_c1, dw_c2, dw_c3; // addr and data_write from clients
output [15:0] dr_c1, dr_c2, dr_c3; // data read from clients
input wr_c1, wr_c2, wr_c3, rd_c1, rd_c2, rd_c3, cs_c1, cs_c2, cs_c3; // control from clients
output [15:0] addr_m, dw_m; // addr and data write to memory
input [15:0] dr_m;
output wr_m, rd_m, cs_m; // control the memory
output rdy_c1, rdy_c2, rdy_c3;
reg [15:0] dr_c1, dr_c2, dr_c3, dw_m, addr_m;
reg wr_m, rd_m, cs_m;
reg [1:0] cnt;
always #(posedge clk or negedge rst_n)
if (~rst_n)
cnt <= 0;
else if(cnt == 2'd2)
cnt <= 0;
else
cnt <= cnt + 1;
always #(*) // Verilog 2001, if not recognizable, fill in yourself
begin
case(cnt)
0: begin
dw_m = dw_c1;
wr_m = wr_c1;
cs_m = cs_c1;
rd_m = rd_c1;
dr_c1 = dr_m;
end
1: begin
dw_m = dw_c2;
wr_m = wr_c2;
cs_m = cs_c2;
rd_m = rd_c2;
dr_c2 = dr_m;
end
default: begin
dw_m = dw_c3;
wr_m = wr_c3;
cs_m = cs_c3;
rd_m = rd_c3;
dr_c3 = dr_m;
end
endcase
end
assign rdy_c1 = (cnt == 0) & cs_c1;
assign rdy_c2 = (cnt == 1) & cs_c2;
assign rdy_c3 = (cnt == 2) & cs_c3;
endmodule
However, this is only OK when the access rates of all clients are lower than once per three cycles. If the access rate is variant and higher than that, you will need a real arbiter in the mem_ctl module. I think a round-robin arbiter will be fine.
The final comment, if the accumulative access rates of all clients is larger than once per cycle, it is impossible to handle in hardware. In that case, you will need to do it in other ways.
I'm an FPGA noob trying to learn Verilog. How can I "assign" a value to a reg in an always block, either as an initial value, or as a constant. I'm trying to do something like this in the code below. I get an error because the 8 bit constant doesn't count as input. I also don't want to trigger the always off of a clock. I just want to assign a register to a specific value. As I want it to be synthesisable I can't use an initial block. Thanks a lot.
module top
(
input wire clk,
output wire [7:0] led
);
reg [7:0] data_reg ;
always #*
begin
data_reg = 8'b10101011;
end
assign led = data_reg;
endmodule
You can combine the register declaration with initialization.
reg [7:0] data_reg = 8'b10101011;
Or you can use an initial block
reg [7:0] data_reg;
initial data_reg = 8'b10101011;
You should use what your FPGA documentation recommends. There is no portable way to initialize register values other than using a reset net. This has a hardware cost associated with it on most synthesis targets.
The other answers are all good. For Xilinx FPGA designs, it is best not to use global reset lines, and use initial blocks for reset conditions for most logic. Here is the white paper from Ken Chapman (Xilinx FPGA guru)
http://japan.xilinx.com/support/documentation/white_papers/wp272.pdf
The always #* would never trigger as no Right hand arguments change. Why not use a wire with assign?
module top (
input wire clk,
output wire [7:0] led
);
wire [7:0] data_reg ;
assign data_reg = 8'b10101011;
assign led = data_reg;
endmodule
If you actually want a flop where you can change the value, the default would be in the reset clause.
module top
(
input clk,
input rst_n,
input [7:0] data,
output [7:0] led
);
reg [7:0] data_reg ;
always #(posedge clk or negedge rst_n) begin
if (!rst_n)
data_reg <= 8'b10101011;
else
data_reg <= data ;
end
assign led = data_reg;
endmodule
Hope this helps
When a chip gets power all of it's registers contain random values. It's not possible to have an an initial value. It will always be random.
This is why we have reset signals, to reset registers to a known value. The reset is controlled by something off chip, and we write our code to use it.
always #(posedge clk) begin
if (reset == 1) begin // For an active high reset
data_reg = 8'b10101011;
end else begin
data_reg = next_data_reg;
end
end