Verilog: code for MUX - verilog

I am working on a verilog code with following requirements:
It is Fully synchronous.
Implement Muxes between 11 buses where each bus is 8-bits wide.
It has 2 cycles of latency.
It has Optimized for maximum clock frequency.
I have written this code so far:
module muxcase (a,b,c,d,e,f,g,h,i,j,k, select, op, clk, reset);
input [7:0] a,b,c,d,e,f,g,h,i,j,k;
input [3:0] select;
output [7:0] op;
reg op;
input reset, clk;
integer count= 2’b00;
integer temp= 2’b00;
always # (posedge clk)
begin
if (reset==1’b1)
begin
count=2’b00;
op=8’b00000000;
select=4’b0000;
end
if (reset==1’b0)
begin
if (count <3)
begin
count=count+1;
temp=count;
end
end
case (select)
4’b0000: op=a;
4’b0001: op=b;
4’b0010: op=c;
4’b0011: op=d;
4’b0100: op=e;
4’b0101: op=f;
4’b0110: op=g;
4’b0111: op=h;
4’b1000: op=i;
4’b1001: op=j;
4’b1010: op=k;
endcase
end
endmodule
Now i am not sure how to incorporate the maximum clk frequency part and whether my counter for 2 clock cycles has correct logic. Any help regarding that would be appreciated.
Test Bench:
module mux_tb;
reg [7:0] a,b,c,d,e,f,g,h,i,j,k;
reg [3:0] select;
wire [7:0] op;
initial
begin
a =1,b =1,c = 0,d=0,e=0,f=1,g=1,h=0,i=1,j=0,k=1;
s=4’b0000;
#5 s=4’b0011;
#5 s=4’b0111;
#5 s=4’b1010;
end
muxcase f1 (a,b,c,d,e,f,g,h,I,j,k, select, op, clk, reset);
endmodule

To optimize for maximum clock frequency you need to minimize the gate logic between two FFs (pipeline). That is, instead of doing very long calculation in a single clock cycle, and by that requiring the clock cycle being very long (low frequency), we break the calculation to many small ones, and by that doing more clock cycles, but the clock cycle is shorter (high frequency).
So obviously, it's a tradeoff between latency and throughput.
To pipeline a mux, I would suggest using hierarchical mux tree.
Let's say for simplicity that you have 4 inputs. We can mux inputs 1 and 2 in parallel to inputs 3 and 4, using two small muxes.
We can sample the output of those two muxes, and then on the next cycle mux between the outputs of mux 1 and mux 2, which we calculated at the previous clock cycle.
Below you can see an example of a 4-to-1 pipelined mux with latency of 2.
You can easily expand it to more inputs.
Notice that:
you have 11 inputs to mux, so your mux tree will not be balanced.
You should use different bits of the select for each stage
You should sample the select along with data
Personally, I would have written it totally different coding style, but I tried to keep it as close as possible to yours, to make it more understandable for you. Also, I didn't check it compiles or behaves as expected
module pipelined_mux_4to1 (
input clk,
input [1:0] select,
input [7:0] a,
input [7:0] b,
input [7:0] c,
input [7:0] d,
output reg [7:0] out
);
//first cycle muxes
reg [7:0] mux_a_b;
always #*
case (select[0])
1'b0 : mux_a_b = a;
1'b1 : mux_a_b = b;
default: mux_a_b = {7{1'bx}};
endcase
reg [7:0] mux_c_d;
always #*
case (select[0])
1'b0 : mux_c_d = c;
1'b1 : mux_c_d = d;
default: mux_c_d = {7{1'bx}};
endcase
//sample first muxes stage and the select
reg [7:0] mux_a_b_ff;
reg [7:0] mux_c_d_ff;
reg select_msb_ff;
always #(posedge clk) begin
mux_a_b_ff <= mux_a_b;
mux_c_d_ff <= mux_c_d;
select_msb_ff <= select[1];
end
//second cycle mux
reg [7:0] mux_final;
always #*
case (select_msb_ff)
1'b0 : mux_final = mux_a_b_ff;
1'b1 : mux_final = mux_c_d_ff;
default: mux_final = {7{1'bx}};
endcase
//sample second mux stage
always #(posedge clk)
out <= mux_final;
endmodule

Related

Modelsim - Object not logged & no signal data while simulating verilog clock divider code

What I'm trying to do: I wish to count numbers from 0 to hexadecimal F and display these on my FPGA board at different frequencies - my board's clock (CLOCK_50) is at 50 MHz and I wish to alter the frequency/speed of the counting based on two input switches on my board (SW[1:0]).
Verilog Code for top-module & clock divider module:
//top level module
module rate_divider (input CLOCK_50, input [1:0] SW, input [1:0] KEY,output [6:0] HEX0);
//Declare parameters that define the # of clock cycles needed to generate an enable pulse
according to the desired frequency.
parameter FREQ_5MHz = 4'd9; //To divide to 5 MHz we need (10-1) cycles,
//since the pulse needs to start at the 9th cycle.
parameter FULL50_MHz = (4'd1); //The CLOCK_50's Frequency.
//Select the desired parameter based on the input switches
reg [3:0] cycles_countdown;
wire enable_display_count;
wire [3:0] selected_freq;
always #(*)
case (SW)
2'b00: cycles_countdown = FULL50_MHz;
2'b01: cycles_countdown = FREQ_5MHz;
default : cycles_countdown = FULL50_MHz;
endcase
assign selected_freq = cycles_countdown;
//wire that is the output of the display_counter and input to the 7 segment
wire [3:0] hex_value;
// instantiate my other modules
clock_divider_enable freq_divider (.d(selected_freq), .clk(CLOCK_50), .reset(KEY[0]),
.enable(enable_display_count));
display_counter count_hex (.enable(enable_display_count), .clk(CLOCK_50), .hex_out(hex_value), .reset(KEY[1]));
hex_decoder HX0 (.hex_digit(hex_value), .segments(HEX0[6:0]));
endmodule
//the clock_divider sub-circuit.
module clock_divider_enable (input [3:0] d, input clk, reset,
output enable);
reg [3:0] q;
always #(posedge clk)
begin
if (!reset || !q)
q <= d;
else
q <= q - 4'd1;
end
assign enable = (q == 4'h0) ? 1'b1 : 1'b0;
endmodule
ModelSim Code:
vlib work
vlog rate_divider.v
vsim rate_divider
log {/*}
add wave {/*}
#initial reset - using KEY[1:0]. Note: active low synchronous reset.
force {CLOCK_50} 1
force {KEY[0]} 0
force {KEY[1]} 0
run 10ns
#choose 5 MHz as the desired frequency - turn SW[0] high.
force {CLOCK_50} 0 0ns, 1 {10ns} -r 20ns
force {KEY[0]} 1
force {KEY[1]} 1
force {SW[0]} 1
force {SW[1]} 0
run 600ns
Problems I am facing:
Here's the thing - when I don't use the always block to select a parameter, and pass a desired parameter to the wire selected_freq, my simulation works fine - I can see the expected enable pulse.
HOWEVER, if I use the always block, the reg cycles_countdown does get the correct value assigned, BUT for some reason the enable signal is just a red line. When I select my clock_divider_enable module and add it's 'q' signal onto my waveform, it is red too and shows no data, and the object q is "not logged". As such, I'm unable to debug and figure out what exactly the problem with my code is.
It'd be great if someone could help with how to fix the simulation issue rather than just point out the issue with my Verilog code since I want to learn how to use ModelSim efficiently so that in the future debugging will be easier for me.
Equipment Used:
FPGA: Altera De-1-SoC, Cyclone V chip
CAD/Simulation Tools: Altera Quartus II Lite 17.0 + ModelSim Starter Edition
SW wasn't given an initial value, therefore it is high-Z (X if connected to a reg).
I'm guessing when you used the parameter approach you were parameterizing cycles_countdown. Some simulators do not trigger #* at time-0. So if there isn't a change on the senctivity list, then the block may not execute; leaving cycles_countdown as its initial value (4'hX).
Instead of driving your test with TCL commands, you can use create a testbench in with verilog. This testbench should only be used in simulation, not synthesis.
module rate_devider_tb;
reg CLOCK_50;
reg [1:0] SW;
reg [1:0] KEY;
wire [6:0] HEX0;
rate_divider dut( .CLOCK_50(CLOCK_50), .SW(SW), .KEY(KEY), .HEX0(HEX0));
always begin
CLOCK_50 = 1'b1;
#10;
CLOCK_50 = 1'b0;
#10;
end
initial begin
// init input signals
SW <= 2'b01;
KEY <= 2'b00;
// Log file reporting
$monitor("SW:%b KEY:%b HEX0:%h # %t", SW, KEY, HEX0, $time);
// waveform dumping
$dumpfile("test.vcd");
$dumpvars(0, rate_devider_tb);
wait(CLOCK_50 === 1'b0); // initialization x->1 will trigger an posedge
#(posedge CLOCK_50);
KEY <= 2'b01; // remove reset after SW was sampled
#600; // 600ns assuming timescale is in 1ns steps
$finish();
end

Verilog logical error

module ocircuit (ooutp,s0,s1 ,clk,write,raddA,raddB,wadd,wdata);
output [3:0] ooutp;
input clk, write,s0,s1;
input [2:0] raddA;
input [2:0] wadd;
input [2:0] raddB;
input [3:0] wdata;
reg [9:0] ooutp;
wire [3:0] dataA;
wire [3:0] dataB;
reg [9:0] inner;
regfile y (dataA,dataB,clk,write,raddA,raddB,wadd,wdata);
always #(posedge clk) begin
if (s0==0) begin
assign inner = dataA [3:0]*dataB [3:0];
end
else begin
assign inner = ((dataA [3:0]*dataB [3:0])+inner [9:0]);
end
//inner=inner1;
ooutp =s1?inner [9:0]:10'd0;
end
endmodule
This is the code. regfile is a simple register file. In the testbench, s0 = 0 during the first cycle and s0 = 1.
For subsequent cycles, this code should return the value of A*B+C*D by using one adder and one multiplier. In the first cycle, when c0 = 0, the answer that is saved in inner (a register) is right but in the second cycle, when c0 = 1 the answer is wrong.
Por example: A=1; B=2; C=1; D=1;
First cycle: x=A*B=2
Second cycle (C*D)+x=5
I think there is something wrong with this statement
assign inner = ((dataA [3:0]*dataB [3:0])+inner [9:0]);
Any help or hint will be appreciated.
Although assign can be used from within an always block, I think you just wanted to store a value into inner depending upon the value of s0. To do that, use non-blocking assignments ( <= ).
Also, you can directly output to ooutp instead of saving the final result in inner, avoiding a possible glitch in the multiplexer you instantiate here:
ooutp =s1?inner [9:0]:10'd0;
Which, by the way, it should be outside the always block, in an assign line:
assign ooutp = s1? inner [9:0]:10'd0;
module ocircuit (ooutp,s0,s1 ,clk,write,raddA,raddB,wadd,wdata);
output [3:0] ooutp;
input clk, write,s0,s1;
input [2:0] raddA;
input [2:0] wadd;
input [2:0] raddB;
input [3:0] wdata;
reg [9:0] ooutp;
wire [3:0] dataA;
wire [3:0] dataB;
reg [9:0] inner;
regfile y (dataA,dataB,clk,write,raddA,raddB,wadd,wdata);
always #(posedge clk) begin
if (s0==0) begin
inner <= dataA [3:0]*dataB [3:0];
end
else begin
ooutp <= ((dataA [3:0]*dataB [3:0])+inner [9:0]);
end
end
endmodule

always module in Verilog RTL file not working, but working once included in testbench

This might seem like a very naive question, but I have just started working with Verilog (I use Xilinx ISE, if that helps).
I am trying to implement a shift register that shifts input PI by the value specified in the shft port. When I include the shifting logic in the RTL file, the shifting does not work, but when I move the always block corresponding to shifting to the testbench, it works. Please help me with this!
module shift (PI, shft, clk, PO);
input [7:0] PI;
input clk;
input [7:0] shft;
output reg [13:0] PO;
reg [7:0] shft_reg;
always #(posedge clk) begin
if (shft_reg[0]||shft_reg[1]||shft_reg[2]||shft_reg[3]||shft_reg[4]||shft_reg[5]||shft_reg[6]||shft_reg[7]) begin
PO <= {PO, 0};
shft_reg <= shft_reg-1;
end
end
endmodule
module shift (
input wire clk;
input wire load; // load shift register from input
input wire [7:0] PI;
input wire [7:0] shft; // this might need less bits
output wire [13:0] PO;
);
reg [7:0] shft_reg;
reg [13:0] value;
assign PO = value; // PO follows value
always #(posedge clk) begin
if (load) begin // initialize shift register and counter
shft_reg <= shft;
value <= {6'b0,PI};
end
else if (shft_reg) begin // if counter not reached end...
shft_reg <= shft_reg - 1; // decrement, and
value <= {value[13:1],1'b0}; // shift left value 1 bit
end
end
end
endmodule
Recall that Verilog supports the >> and << operators. For non-constants many-bit operands, this may be a waste of multiplexers, though:
module shiftcomb (
input wire [7:0] PI; // this value is left shifted
input wire [2:0] shft; // 0 to 7 bits positions
output wire [14:0] PO; // and is outputted to PO
);
assign PO = PI<<shft; // this will generate 15 mutlplexers:
// each one with 8 inputs, 3 bit select,
// and 1 output.
endmodule
Note that || is a logical or and idealy should be used with logical statments such as (shft_reg[0] == 1'b1 ) || ( shft_reg[1] == 1'b1).
Your if statment is really bitwise ORing all of the bits ie
shft_reg[0] | shft_reg[1] | shft_reg[2] | ...
You can use the OR Reduction operator :
|shft_reg
Your supplied code had typo'd PI for PO.
always #(posedge clk) begin
if (|shft_reg) begin
PO <= {PI, 0}; //PI input
shft_reg <= shft_reg-1;
end
end

What is the wrong with my verilog code?

i wanna write register file in verilog that is write and read data registers.
this is my code:
module registerfile(writeaddr1,writedata1,readaddr2,readdata2,readaddr3,readdata3,write,clock);
input [4:0] writeaddr1, readaddr2, readaddr3;
input [31:0] writedata1;
output[31:0]readdata2,readdata3;
reg [31:0]readdata2,readdata3;
input write,clock;
reg [31:0] cells [0:31];
always #(posedge clock)
begin
if (write == 1) cells[writeaddr1] =writedata1;
readdata2 = cells[readaddr2];
readdata3 = cells[readaddr3];
end
endmodule
and this is my test bench.
module testreg;
reg [3:0]addr1,addr2,addr3;
reg [31:0]data1;
reg write;
wire [31:0]data2,data3;
reg clock ; //Rising edge every 10 timesteps
registerfile regf(addr1,data1,addr2,data2,addr3,data3,write,clock);
initial begin
addr1=1;
addr2=2;
addr3=3;
write=0;
data1=32'bx;
clock=0;
#10
addr1=1;
addr2=1;
addr3=3;
write=1;
data1=30;
clock=1;
#10
$finish;
end
endmodule
but i don't know why data2 between 10 and 20 is xxx? I am write 30 in that location:(
If the period of clk is 20ns, Between 0ns and 20ns first write is applied, but data2 is not the same data1, because read and write is simultaneous and when you write a value on memory, at the next clk rising edge you can read the same value from memory. Then between 20ns and 40ns (on clk rising edge) data2 is equal to data1.
In the module testreg size of addr1 should be [4:0] :
reg [4:0] addr1,addr2,addr3;
As Greg said in the module registerfile it's better to use non-blocking assignments (<=) such as the following code :
always #(posedge clock)
if (write) begin
cells[writeaddr1] <= writedata1;
readdata2 <= cells[readaddr2];
readdata3 <= cells[readaddr3];
end
Just use the following code and continue to run simulation until 40ns :
initial begin
addr1=1;
data1=30;
addr2=1;
write=1;
end
initial begin
clock = 0;
forever #10 clock = ~clock;
end
I simulated your code with the above changes and could get the correct result.

Circuit behaves poorly in timing simulation but alright in behavioral - new to verilog

I'm new to verilog development and am having trouble seeing where I'm going wrong on a relatively simple counter and trigger output type design.
Here's the verilog code
Note the code returns the same result whether or not the reg is declared on the output_signal without the internal_output_buffer
`timescale 1ns / 1ps
module testcounter(
input wire clk,
input wire resetn,
input wire [31:0] num_to_count,
output reg [7:0] output_signal
);
reg [31:0] counter;
initial begin
output_signal = 0;
end
always#(negedge resetn) begin
counter = 0;
end
always#(posedge clk) begin
if (counter == num_to_count) begin
counter = 0;
if (output_signal == 0) begin
output_signal = 8'hff;
end
else begin
output_signal = 8'h00;
end
end
else begin
counter = counter + 1;
end
end
assign output_signal = internal_output_buffer;
endmodule
And the code is tested by
`timescale 1ns / 1ps
module testcounter_testbench(
);
reg clk;
reg resetn;
reg [31:0] num_to_count;
wire [7:0] output_signal;
initial begin
clk = 0;
forever #1 clk = ~clk;
end
initial begin
num_to_count = 20;
end
initial begin
#7 resetn = 1;
#35 resetn = 0;
end
testcounter A1(.clk(clk),.resetn(resetn),.num_to_count(num_to_count),.output_signal(output_signal));
endmodule
Behavioral simulation looks as I expected
But the timing simulation explodes
And for good measure: the actual probed execution blows up and looks like
Any tips would be appreciated. Thanks all.
The difference between the timing and functional simulations is that a timing simulation models the actual delay of logic gates while the functional simulation just checks if values are correct.
For e.g. if you have a simple combinational adder with two inputs a and b, and output c. A functional simulation will tell you that c=a+b. and c will change in the exact microsecond that a or b changes.
However, a timing simulation for the same circuit will only show you the result (a+b) on c after some time t, where t is the delay of the adder.
What is your platform? If you are using an FPGA it is very difficult to hit 500 MHz. Your clock statement:
forever #1 clk = ~clk;
shows that you toggle the clock every 1ns, meaning that your period is 2ns and your frequency is 500MHz.
The combinational delay through FPGA resources such as lookup tables, multiplexers and wire segments is probably more than 2ns. So your circuit violates timing constraints and gives wrong behaviour.
The first thing I would try is to use a much lower clock frequency, for example 100 MHz and test the circuit again. I expect it to produce the correct results.
forever #5 clk = ~clk;
Then to know the maximum safe frequency you can run at, look at your compilation reports in your design tools by running timing analysis. It is available in any FPGA CAD tool.
Your code seems working fine using Xilinx Vivado 14.2 but there is only one error which is the following line
assign output_signal = internal_output_buffer;
You can't assign registers by using "assign" and also "internal_output_buffer" is not defined.
I also personally recommend to set all registers to some values at initial. Your variables "resetn" and "counter" are not assigned initially. Basicly change your code like this for example
reg [31:0] counter = 32'b0;
Here is my result with your code:
Your verilog code in the testcounter looks broken: (a) you're having multiple drivers, and (b) like #StrayPointer notices, you're using blocking assignments for assigning Register (Flip-Flop) values.
I'm guessing your intent was the following, which could fix a lot of simulation mismatches:
module testcounter
(
input wire clk,
input wire resetn,
input wire [31:0] num_to_count,
output reg [7:0] output_signal
);
reg [31:0] counter;
always#(posedge clk or negedge resetn) begin
if (!resetn) begin
counter <= 0;
end else begin
if (counter == num_to_count) begin
counter <= 0;
end else begin
counter <= counter + 1;
end
end
end
assign output_signal = (counter == num_to_count) ? 8'hff : 8'h00;
endmodule

Resources