I have different modules instantiated in one single module. I want to execute them in sequence, I have enable and acknowledgement signals of all modules how can I do this?
Following is the code:
module memorycontroller(
input [7:0] A,
input [7:0] B,
input [1:0] adrress,
input clk,
output [7:0] A_mem,
output [7:0] B_mem
);
reg LMwrEnable, localmemEnable;
integer LMwrack, localmemack;
reg [7:0] A1, B1;
initial
begin
LMwrEnable = 1;
localmemEnable = 0;
end
memorywrite LMwr (
.clk ( clk ),
.A ( A ),
.B ( B ),
.adr ( adrress ),
.enable ( LMwrEnable ),
.ack ( LMwrack )
);
bram_tdp localmem (
.a_clk ( clk ),
.a_wr ( 1'b0 ),
.a_addr ( adrress ),
.a_din ( A1 ),
.a_dout ( A_mem ),
.b_clk ( clk ),
.b_wr ( 1'b0 ),
.b_addr ( adrress+1'b1 ),
.b_din ( B1 ),
.b_dout ( B_mem ),
.enable ( localmemEnable ),
.ack ( localmemack )
);
always#(posedge clk)
begin
if(LMwrack)
localmemEnable = 1;
end
endmodule
In initial statement I've enabled only LMwr module in initial block and on its ack signal I have enabled localmem module in always block but this is giving me wrong result. Can you tell me how to execute different modules in sequence?
Following is the memorywrite module
module memorywrite(
input clk,
input [7:0] A,
input [7:0] B,
input [1:0] adr,
input enable,
output ack
);
wire [7:0] C,C1;
bram_tdp localmem (
.a_clk(clk),
.a_wr(1'b1),
.a_addr(adr),
.a_din(A),
.a_dout(C),
.b_clk(clk),
.b_wr(1'b1),
.b_addr(adr+1'b1),
.b_din(B),
.b_dout(C1),
.enable(enable),
.ack(ack)
);
endmodule
This above code writes to the memory.
Following is the actual memory module which is being written by 2nd code stated above and read by 1st code stated above
module bram_tdp #(
parameter DATA = 8,
parameter ADDR = 2
) (
input enable,
output ack,
// Port A
input wire a_clk,
input wire a_wr,
input wire [ADDR-1:0] a_addr,
input wire [DATA-1:0] a_din,
output reg [DATA-1:0] a_dout,
// Port B
input wire b_clk,
input wire b_wr,
input wire [ADDR-1:0] b_addr,
input wire [DATA-1:0] b_din,
output reg [DATA-1:0] b_dout
);
// Shared memory
reg [DATA-1:0] mem [(2**ADDR)-1:0];
// Port A
always #(posedge a_clk) begin
if(enable) begin
a_dout <= mem[a_addr];
if(a_wr) begin
a_dout <= a_din;
mem[a_addr] <= a_din;
end
end
end
// Port B
always #(posedge b_clk) begin
if(enable) begin
b_dout <= mem[b_addr];
if(b_wr) begin
b_dout <= b_din;
mem[b_addr] <= b_din;
end
end
end
assign ack=1;
endmodule
Here is testbench:
module mmTesting;
// Inputs
reg [7:0] A;
reg [7:0] B;
reg [1:0] adrress;
reg clk;
// Outputs
wire [7:0] A_mem;
wire [7:0] B_mem;
// Instantiate the Unit Under Test (UUT)
memorycontroller uut (
.A(A),
.B(B),
.adrress(adrress),
.clk(clk),
.A_mem(A_mem),
.B_mem(B_mem)
);
initial begin
// Initialize Inputs
A = 0;
B = 0;
adrress = 0;
clk = 0;
// Wait 100 ns for global reset to finish
#100;
A = 5;
B = 5;
adrress = 0;
#100 A = 6;
B = 2;
adrress = 1;
// Add stimulus here
end
always #5 clk=!clk;
endmodule
Result should be same as what I am writing to the memory.
Just to clarify that Verilog is a hardware description and that both instantiations (not modules, as an uninstantiated module does not exist) can be executed and exist in parallel, unlike the C equivalent which would execute one then the other.
If you have instance A and B, you just need a FSM (Finite State Machine) to enable A wait for its completion signal, then disabling A enable B, waiting for B to complete and repeat.
NB: if the commented out code is not relevant to the question can it be removed, it is good practise to reduce your question to the minimum amount of code required to reproduce the problem.
Related
module Vr_ALU (A, B, ALUCtrl, ALUOut, Zero);
input [31:0] A;
input [31:0] B;
input [2:0] ALUCtrl;
output [31:0] ALUOut;
output Zero;
wire [31:0] sig_a;
wire [31:0] sig_b;
wire [31:0] sig_sum;
wire sig_cin;
wire sig_cout;
always #(*) begin
if(ALUCtrl==2'b010)
Vr_ripple_adder_M_bits U1(.A(sig_a), .B(sig_b), .CIN(sig_cin), .S(sig_sum), .COUT(sig_cout));
else if(ALUCtrl==2'b110)
Vr_ripple_adder_M_bits U2(.A(sig_a), .B(~sig_b), .CIN(~sig_cin), .S(sig_sum), .COUT(~sig_cout));
else ALUOut = 2'bx;
end
assign Zero = (ALUCtrl==2'b110 && ALUOut==0)? 1:0;
endmodule
at this code, I try to make module work as adder when ALUCtrl is 010, and as subtractor when ALUCtrl is 110. But I'm having 'checker not found. Instantiation must be of a visible checker' problem.
Need help.
You cannot instantiate modules in always blocks. You cannot instantiate module conditionally. Modules represent hardware and as such they are always present.
Instead you can use muxes to switch inputs in your module. For example,
reg[31:0] sig_b_temp;
reg sig_cin_temp;
reg sig_cout_temp;
reg sig_cout; // uou need 'reg' for this example.
// muxes
always #(*) begin
if(ALUCtrl==2'b010) begom
//inuts
sig_cin_temp = sig_sin;
sig_b_temp = sig_b;
//outputs
sig_cout = sig_cout_temp;
end
else begin
//inputs
sig_cin_temp = ~sig_sin;
sig_b_temp = ~sig_b;
//output
sig_cout = ~sig_cout_temp;
end
end
//single module instance
Vr_ripple_adder_M_bits U1(.A(sig_a),
.B(sig_b_temp),
.CIN(sig_cin_temp),
.S(sig_sum),
.COUT(sig_cout_temp));
Note, the code above will not compile with
I've encountered a problem of unexpected high impedance state on output ports of my modules. Code of the module that instantiates other modules is following:
`timescale 1ns/1ps
module column(
input wire clk,
input wire reset,
input wire trigger,
input wire [7:0] latency
);
localparam AMOUNT_OF_REGIONS = 3;
wire [24:0] o_data [0:AMOUNT_OF_REGIONS-1];
wire [1:0] up_in [0:AMOUNT_OF_REGIONS-1];
//same declarations for do_in, up_out, do_out
assign up_in[0] = 0;
assign do_in[AMOUNT_OF_REGIONS-1] = 0;
generate
genvar i;
for (i = 0; i < AMOUNT_OF_REGIONS; i = i + 1) begin : multiple_regions_instantiation
if ((i == 0) || (i == AMOUNT_OF_REGIONS-1)) begin
region tmp(
clk,
reset,
trigger,
latency,
up_in[i],
do_in[i],
up_out[i],
do_out[i],
o_data[i]
);
end
else begin
region tmp(
clk,
reset,
trigger,
latency,
do_out[i-1],
up_out[i+1],
do_in[i-1],
up_in[i+1],
o_data[i]
);
end
end
endgenerate
endmodule
Port declaration of instantiatable modules is like this:
module region(
input wire clk,
input wire reset,
input wire trigger,
input wire [7:0] latency,
input wire [1:0] up,
input wire [1:0] do,
output reg [1:0] to_up,
output reg [1:0] to_do,
output reg [24:0] odata
);
Assignment of an output is made in initial block and looks like this:
initial begin
latency_cnt = 255;
start_cnt = 0;
preset = 0;
read_out = 0;
begin: hit_generation
cnt = 0;
forever begin
cnt = cnt + 1;
fork
#20 hit0 = ($random > 0) ? 1 : 0;
#20 hit1 = ($random > 0) ? 1 : 0;
#20 hit2 = ($random > 0) ? 1 : 0;
#20 hit3 = ($random > 0) ? 1 : 0;
to_up = {hit1, hit0};
to_do = {hit3, hit2};
join
if (cnt == 10000) disable hit_generation;
end
end
end
So, now the problem is, if it AMOUNT_OF_REGIONS == 3 or 2 then everything works fine, but if i'm trying to increase its value then for all the regions that are between 1 and AMOUNT_OF_REGIONS-2 (including), their inputs and outputs are messed up (2'bzz). But 0 region sends info to region 1 pretty well, and AMOUNT_OF_REGIONS-1 region sends the info properly to it's neighbor.
Test bench is just instantiating a column and generates a trigger and clk signals. I've read that if there are only wires connections without attachment to the registers that can cause high impedance state, but as far as i can see, i'm connecting wires to the output registers...Dear all, what could be a problem of it? I'm using Icarus Verilog, if it matters.
Accidentally, i've found the root of my problem. I will leave an answer, may be it will help some day to somebody who will be stuck in situation like this.
I made the wrong port assignment, so, i guess, they was cycled or something like that. The problem was that here:
region tmp(
clk,
reset,
trigger,
latency,
do_out[i-1],
up_out[i+1],
do_in[i-1],
up_in[i+1],
o_data[i]
);
I assigned input ports of module to output of another and it was the mistake...
So the proper way of assigning ports in such situation is like this (full code of instantiation cycle):
generate
genvar i;
for (i = 0; i < AMOUNT_OF_REGIONS; i = i + 1) begin : multiple_regions_instantiation
if (i == 0) begin
region tmp(
clk,
reset,
trigger,
latency,
up_in[i],
do_in[i],
up_out[i],
up_in[i+1], //CHANGED
o_data[i]
);
end
else if (i == AMOUNT_OF_REGIONS-1) begin
region tmp(
clk,
reset,
trigger,
latency,
up_in[i],
do_in[i],
do_in[i-1], //CHANGED
do_out[i],
o_data[i]
);
end
else begin
region tmp(
clk,
reset,
trigger,
latency,
up_in[i], //CHANGED
do_in[i], //CHANGED
do_in[i-1],
up_in[i+1],
o_data[i]
);
end
end
endgenerate
Hope it will help somebody!
module accumulator (
input [7:0] A ,
input reset,
input clk,
output reg carryout,
output reg overflow,
output reg [8:0] S,
output reg HEX0,
output reg HEX1,
output reg HEX2,
output reg HEX3
);
reg signA;
reg signS;
reg [7:0] magA;
reg [7:0] magS;
reg Alarger;
initial begin
S = 9'b000000000;
end
always_ff # (posedge clk, posedge reset) begin
if (reset) begin
S = 9'b000000000;
end
else begin
begin
signA <= A[7]; //Is A negative or positive
signS <= S[7];
S <= A + S;
end
if (signA == 1) begin //A is negative so magnitude is of 2s compliment
magA <= (~A[7:0] + 1'b1);
end
else begin
magA <= A;
end
if (signS == 1) begin //sum is negative so magnitude is of 2s compliment
magS <= (~S[7:0] + 1'b1);
end
else begin
magS <= S;
end
if (magA > magS) begin
Alarger <= 1'b1; //Magnitude of A is larger than magnitude of sum
end
else begin
Alarger <= 1'b0;
end
if ((signA == 1) & (Alarger == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (Alarger == 0) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (signA == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 0) & (signA == 0) & (S[7] == 1)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if (S[8] == 1) begin //carryout occurred
carryout <= 1'b1;
overflow <= 1'b0;
S <= 9'b000000000; //sum no longer valid
end
else begin
carryout <= 1'b0;
end
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
end
end
endmodule
I am trying to make an accumulator that adds A (8 digit binary value that can be signed or unsigned) repeatedly to the sum. Once the sum is computed, then sum and A should display the value on 4 hex display LEDs (2 LEDs for A and 2 LEDs for sum). However, I am having a hard time getting it to compile. I have searched the error code and it seems like a general error for a syntax error and can have several meanings.
The error is the result of these two lines:
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
Here, it appears you have a module named display_hex which converts an 8-bit value into the needed digits for a seven segment display. You are trying to use the module as if it were a function and modules are very much NOT functions. Modules in Verilog (or SystemVerilog as you are using, but the difference is really token at this point) can be though of as a group of hardware that takes in some inputs and spits out some outputs; and its important to note that they are static things. They either exist in the design or they do not; just like using ICs on a breadboard. The top module is the breadboard and the modules you declare under that module are components you are plugging into the board. The inputs and outputs are the various connections (pins) you must wire up to make everything work.
That said, always blocks (like the always_ff you are using) form a way of describing the logic and registers inside modules. Thus, you do thinks like assign logic/reg variables inside them to describe how the hardware behaves. If you look at your logic, you'll notice that the module declarations are dependent on reset; ie if reset is asserted, these modules wont exist, which doesnt make any sense. Electrical signals don't make entire ICs in a circuit disappear! Thus, you need to pull your module declaration out of your logical description of your acculumator, like so:
module accumulator (
...
);
...
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
...
always_ff #(posedge clk, posedge reset) begin
// Your accumulator logic here
...
end
endmodule
Notice that the module declarations for the display_hex modules are stand alone, as I am declaring these modules exist, not dependence on anything!
However, there are a number of issues with your design besides that:
As you are using SystemVerilog constructs (always_ff), you should declare all of your variables type logic, not reg or left blank (ie, input clk should be input logic clk, reg signA should be logic signA). The logic type just makes everything easier, so use it :)
In your always_ff block, you do reset correctly except that the assignment should really be NBA (use S <= 9'b0;, not S = 9'b0; in the if (reset))
You use NBA inside your always_ff, which is correct, however, it appears you need to use these values right away in the following logic. This will not work as you expect, or at least it will not act within the same clock cycle. To fix this, youll need to decide what should be a register and what should just be values resulting from intermediate logic, then create a separate always_comb for the intermediate values.
I am making the assumption that the HEX variables are meant for seven segment displays, so they should probably declared at least [6:0] HEXn
I was not able to reproduce the exact error, but moving the instantiations of display_hex outside always_ff resolves the main issue:
module accumulator
(
/* ... */
);
// ...
always_ff # (posedge clk, posedge reset) begin
/* ... */
end
display_hex h1 (
/* ... */
);
display_hex h2 (
/* ... */
);
endmodule
Another thing: The code drives variable S from initial as well as always. This creates multiple drivers and the code will not compile. To fix this, remove the initial completely, you don't need it since S will be set to 0 when reset is asserted.
OR
You can move all the logic into the initial block; it'd look something like this (but this, most probably, won't synthesize):
initial begin
S = 0;
forever begin
wait #(posedge clock);
// Do stuff here ..
end
end
I am simulating a MIPS processor in Verilog for class, I am having the strangest problem. When I pass an instruction (a 32-bit bus) to the main module, it somehow changes. For example, when I set the instruction to 00100000000010000000000000000001, inside the module I print out the instruction as 00101001111010000000000000000001, which is clearly different. No inner modules directly interact with the inside instruction, as it just gets broken up into various other parts. What could be causing the bits to change simply by passing the bus to a module?
Here is the main processor code and test bench:
module SingleCycleProc(clk, instruction);
// input Reset_L, clk;
// input [31:0] startPC;
// output [31:0] dmemOut;
// reg [31:0] dmemOut;
input clk;
input [31:0] instruction;
//Fetch instruction and get new program counter
//wire [31:0] instruction, PC_out;
//reg [31:0] PC;
//InstrMem(PC, instruction);
wire [31:0] sign_extended;
//ProgramCounter(PC, PC_out, zero, sign_extended);
//Break up instruction into basic components
reg [5:0] opcode;
reg [5:0] funct;
reg [15:0] immediate;
reg [25:0] address;
reg [4:0] RSAddr, RTAddr, RDAddr;
wire [31:0] RSData, RTData, RDData;
SIGN_EXTEND(immediate, sign_extended);
//Generate CPU and ALU control bits
wire regDST, ALUSrc, memToReg, regWrite, memRead, memWrite, branch;
wire [1:0] ALUOp;
CPU_Control_unit(opcode, regDST, ALUSrc, memToReg, regWrite, memRead, memWrite, branch, ALUOp);
wire [3:0] alu_control;
ALU_Control_Unit(alu_control, funct, ALUOp);
//Generate the input addresses to the regfile, and retrieve data from regfile
wire [4:0] out;
MUX5_2to1(RTAddr, RDAddr, regDST, out);
RegFile(RSData, RTData, RSAddr, RTAddr, RDData, RDAddr, regWrite, clk);
//select intputs to the ALU and do calculation
wire [31:0] alu_in1;
MUX32_2to1(RTData, sign_extended, ALUSrc, alu_in1);
wire [31:0] alu_out;
wire overflow, cin, cout, zero, PCSrc;
wire [31:0] result;
and(PCSrc, branch, zero);
ALU_behav(RSData, alu_in1, alu_control, result, overflow, cin, cout, zero);
wire [31:0] memReadData;
DataMem(result, clk, memRead, memWrite, RTData, memReadData);
MUX32_2to1(result, memReadData, memToReg, RDData);
always #(negedge clk) begin
// assign PC = PC + 4;
assign opcode = instruction[31:26];
assign funct = instruction[5:0];
assign immediate = instruction[15:0];
assign address = instruction[25:0];
assign RSAddr = instruction[25:21];
assign RTAddr = instruction[20:16];
assign RDAddr = instruction[15:11];
// assign dmemOut = RDData;
end
// always #(~Reset_L) assign PC = startPC;
//Monitor changes in the program counter
// always #(PC)
// #10 $display($time," PC=%d Instr: op=%d rs=%d rt=%d rd=%d imm16=%d funct=%d",
// PC,instruction[31:26],instruction[25:21],instruction[20:16],instruction[15:11],instruction[15:0],instruction[5:0]);
//Monitors memory writes
always #(clk)
begin
#1 $display($time, " clk=%b instruction=%b", clk, instruction);
// #1 $display($time " clk=%b opcode=%b", clk, opcode);
// #1 $display($time,
// " clock=%b RSAddr=%d RSData=%d RTAddr=%d RTData=%d",
// clk, RSAddr, RSData, RTAddr, RTData);
// #1 $display($time, " clk=%b regDST=%b regWrite=%b ALUSrc=%b memRead=%b memWrite=%b memToReg=%b branch=%b ALUOp=%b ", clk, regDST, regWrite, ALUSrc, memRead, memWrite, memToReg, branch, ALUOp);
end
endmodule
module testCPU(clk, Reset_L, startPC, testData);
input clk;
input [31:0] testData;
output Reset_L;
output [31:0] startPC;
reg Reset_L;
reg [31:0] startPC;
reg [31:0] instruction;
SingleCycleProc(clk, instruction);
initial begin
// Your program 1
// Reset_L = 0; startPC = 0 * 4;
// #101 // insures reset is asserted across negative clock edge
// Reset_L = 1;
// #10000; // allow enough time for program 1 to run to completion
// Reset_L = 0;
// #1 $display("Program 1: Result: %d", testData);
//addi $8, $0, 1
instruction = 00100000000010000000000000000001;
#100
//add $8, $8, $8
instruction = 00000001000010000100000000100000;
#100
$finish;
end
endmodule // testCPU
module TopProcessor;
wire reset, clk, Reset_L;
wire [31:0] startPC;
wire [31:0] testData;
m555 system_clock(clk);
testCPU(clk, Reset_L, startPC, testData);
//SingleCycleProc SSProc(clk, Reset_L, startPC, testData);
endmodule // TopProcessor
You are not telling Verilog that the instruction is a binary number, so it is interpreting it as decimal. You need this:
instruction = 32'b00100000000010000000000000000001;
#100
//add $8, $8, $8
instruction = 32'b00000001000010000100000000100000;
Additionally, you should not be putting assign statements inside an always block. If you want these to be registers, use the verilog non-blocking assignment operator <= rather than the assign statement. Or if you want them to be wires, you can keep the assign just move them outside the always block.
Also, try not to mix posedge and negedge. Stick to posedge.
I am trying to design a simple 8-bit 2's complementor. Here is my code:
twos_complement_of_8bits.v
//`include "complementor.v"
module twos_complement_of_8bits(output [7:0] out, input [7:0] in);
integer i;
initial
begin
for(i = 0; i <= 7; i = i + 1)
complementor C(out[i], in[i]);
end
assign out = out + 1;
endmodule
I got an error at this line:
complementor C(out[i], in[i]);
Syntax error near 'C' found.
How can I fix it?
I think you can eliminate your complementor module, then change your twos_complement_of_8bits as follows:
module twos_complement_of_8bits (output [7:0] out, input [7:0] in);
assign out = ~in + 1;
endmodule
If that doesn't give you the output you want, please show some expected output values.
In more complicated situations, you can place arrays of instances of modules or use a generate block.
Here is an example of how to use a generate block:
module twos_complement_of_8bits (output [7:0] out, input [7:0] in);
wire [7:0] out_ones;
genvar i;
generate
for (i=0; i<=7; i=i+1) begin
complementor C[i] (out_ones[i], in[i]);
end
endgenerate
assign out = out_ones + 1;
endmodule