How does verilog concatenation work when used as both sides of a non-blocking assignement? - verilog

I am a beginner when it comes to verilog or any HDL. While working on a project I found a post where someone uses concatenation in both sides of the non-blocking assignment.
Like so:
{tf0, th0,tl0} <= {1'b0, th0, tl0}+ 1'b1;
I don't really understand how this works.
This is part of an implementation of a timer module in a Intel 8051 micro-controller implementation .
This is the whole relevant code part for this problem:
module oc8051_tc (clk, rst,
data_in,
wr_addr,
wr, wr_bit,
ie0, ie1,
tr0, tr1,
t0, t1,
tf0, tf1,
pres_ow,
//registers
tmod, tl0, th0, tl1, th1);
input [7:0] wr_addr,
data_in;
input clk,
rst,
wr,
wr_bit,
ie0,
ie1,
tr0,
tr1,
t0,
t1,
pres_ow;
output [7:0] tmod,
tl0,
th0,
tl1,
th1;
output tf0,
tf1;
reg [7:0] tmod, tl0, th0, tl1, th1;
reg tf0, tf1_0, tf1_1, t0_buff, t1_buff;
wire tc0_add, tc1_add;
assign tc0_add = (tr0 & (!tmod[3] | !ie0) & ((!tmod[2] & pres_ow) | (tmod[2] & !t0 & t0_buff)));
assign tc1_add = (tr1 & (!tmod[7] | !ie1) & ((!tmod[6] & pres_ow) | (tmod[6] & !t1 & t1_buff)));
assign tf1= tf1_0 | tf1_1;
//
// read or write from one of the addresses in tmod
//
always #(posedge clk or posedge rst)
begin
if (rst) begin
tmod <=#1 `OC8051_RST_TMOD;
end else if ((wr) & !(wr_bit) & (wr_addr==`OC8051_SFR_TMOD))
tmod <= #1 data_in;
end
//
// TIMER COUNTER 0
//
always #(posedge clk or posedge rst)
begin
if (rst) begin
tl0 <=#1 `OC8051_RST_TL0;
th0 <=#1 `OC8051_RST_TH0;
tf0 <= #1 1'b0;
tf1_0 <= #1 1'b0;
end else if ((wr) & !(wr_bit) & (wr_addr==`OC8051_SFR_TL0)) begin
tl0 <= #1 data_in;
tf0 <= #1 1'b0;
tf1_0 <= #1 1'b0;
end else if ((wr) & !(wr_bit) & (wr_addr==`OC8051_SFR_TH0)) begin
th0 <= #1 data_in;
tf0 <= #1 1'b0;
tf1_0 <= #1 1'b0;
end else begin
case (tmod[1:0]) /* synopsys full_case parallel_case */
`OC8051_MODE0: begin // mode 0
tf1_0 <= #1 1'b0;
if (tc0_add)
{tf0, th0,tl0[4:0]} <= #1 {1'b0, th0, tl0[4:0]}+ 1'b1;
end
`OC8051_MODE1: begin // mode 1
tf1_0 <= #1 1'b0;
if (tc0_add)
{tf0, th0,tl0} <= #1 {1'b0, th0, tl0}+ 1'b1;
end
`OC8051_MODE2: begin // mode 2
tf1_0 <= #1 1'b0;
if (tc0_add) begin
if (tl0 == 8'b1111_1111) begin
tf0 <=#1 1'b1;
tl0 <=#1 th0;
end
else begin
tl0 <=#1 tl0 + 8'h1;
tf0 <= #1 1'b0;
end
end
end
`OC8051_MODE3: begin // mode 3
if (tc0_add)
{tf0, tl0} <= #1 {1'b0, tl0} +1'b1;
if (tr1 & pres_ow)
{tf1_0, th0} <= #1 {1'b0, th0} +1'b1;
end
/* default:begin
tf0 <= #1 1'b0;
tf1_0 <= #1 1'b0;
end*/
endcase
end
end

A concatenation on the RHS of the assignment is a packing operation. It is going to take its 3 operands and pack them into a 17-bit value. The first operand (1'b0) becomes the most significant bit(MSB) and the last operand (tl0) becomes the least significant bits(LSBs). That value then gets incremented by one, and the result gets scheduled for assignment to the LHS.
A concatenation on the LHS of the assignment is an unpacking operation. The first operand (tf0) gets the MSB of the result and the last operand (tl0) gets the LSBs.
Note that a packing concatenation may contain read-only literals and constants, but an unpacking concatenation must be all writable variables.

Related

Delay counter not incrementing? FSM

I was writing a code for DAC register and there is delay required. However, in the delay state, the DAC_counter_2 is not incrementing, and delay is not being achieved. I have copied the code to different project and tried to check. The problem still exists. Any help would be great.
module dac_card
( output reg DAC_SCLK,
output reg SYNC,
output reg SDIN,
input MHZ_50_CLK,
input RST,
output reg [7:0] DAC_counter_1,
output reg [7:0] DAC_counter_2
);
reg [7:0] pst_state, nxt_state;
reg [23:0] DAC_reg;
always #(posedge MHZ_50_CLK)
begin
if (RST)
begin
DAC_reg <= 24'hEEEEEE;
SYNC <= 1'b1;
DAC_SCLK <= 1'b0;
SDIN <=1'b0;
DAC_counter_1 <= 8'd0;
DAC_counter_2 <= 8'd0;
pst_state <= 8'd0;
end
else
begin
pst_state <= nxt_state;
DAC_counter_1 <= DAC_counter_1 + 1'b1;
end
end
always #(pst_state or DAC_counter_2)
begin
case (pst_state)
8'd0 : begin
if (DAC_counter_2 == 8'd24)
begin
DAC_counter_2 = 8'd0;
SYNC = 1'b1;
SDIN = 1'b0;
nxt_state = 8'd2;
end
else
begin
SYNC = 1'b0;
DAC_SCLK = 1'b1;
DAC_counter_2 = DAC_counter_2 + 1'b1;
SDIN = DAC_reg [23]; //Writing DAC register
DAC_reg = DAC_reg << 1;
nxt_state = 8'd1;
end
end
8'd1 : begin
DAC_SCLK = 1'b0;
nxt_state = 8'd0;
end
8'd2 : begin
if (DAC_counter_2 == 8'd10) //Minimum delay for SYNC to be low for write mode
begin
SYNC = 1'b1;
DAC_counter_2 = 8'd0;
nxt_state = 8'd3;
end
else
begin
SYNC = 1'b0;
//Not incrementing
DAC_counter_2 = DAC_counter_2 + 1'b1;
end
end
8'd3 : begin
nxt_state = 8'd0;
end
default : begin
nxt_state = 8'd0;
end
endcase
end
endmodule
Here is the test bench
module test_bench
();
//Analog Card DAC wires and registers
reg MHZ_50_CLK;
reg RST;
wire DAC_SCLK;
wire SYNC;
wire SDIN;
wire [7:0] DAC_counter_1;
wire [7:0] DAC_counter_2;
//Instatntiate DAC
dac_card dc (.DAC_SCLK(DAC_SCLK),
.SYNC(SYNC),
.SDIN(SDIN),
.MHZ_50_CLK(MHZ_50_CLK),
.RST(RST),
.DAC_counter_1(DAC_counter_1),
.DAC_counter_2(DAC_counter_2)
);
initial
begin
MHZ_50_CLK = 1'b0;
#10 RST = 1'b1;
#20 RST = 1'b0;
end
always
begin
#10 MHZ_50_CLK <= ~MHZ_50_CLK;
end
endmodule
Here is the waveform. After 24 counts of DAC_counter_2, delay for 8'd10 is not achieved.
You need to make an assignment to nxt_state in all branches of your case statement. This also avoids inferring unintended latches. For example, refer to the line // MISSING nxt_state = below:
8'd2 : begin
if (DAC_counter_2 == 8'd10) //Minimum delay for SYNC to be low for write mode
begin
SYNC = 1'b1;
DAC_counter_2 = 8'd0;
nxt_state = 8'd3;
end
else
begin
SYNC = 1'b0;
//Not incrementing
DAC_counter_2 = DAC_counter_2 + 1'b1;
// MISSING nxt_state =
end
end
As your waves show, once you enter state 2, you remain in state 2. Since DAC_counter_2 is not 10 in state 2, you always execute the else clause, which does not change nxt_state.
There are a couple other issues which may also be causing problems.
Good coding practices recommend making assignments to a reg from a single always block. DAC_counter_2 is assigned in 2 different blocks.
Also, the same signal should not appear on both the LHS and RHS of an assignment in a combinational always block since it creates a feedback loop. For example, DAC_counter_2 = DAC_counter_2 + 1 should probably be in a sequential always block like DAC_counter_1.

Valid-Ready handshake in Verilog

I am trying to learn valid/ready handshake in verilog. In particular, I am interested to use ready as a flag that indicates the successful transaction of data (i.e., ready_in becomes high after valid_out goes high). I would like to explain my problem using a very simple Verilog example. I have written a convolutional encoder (code below)
module Conv_Encoder_Core(
input wire clk,
input wire reset,
input wire in_bit,
output reg out_A,
output reg out_B,
input wire sleep,
input wire valid_in,
input wire ready_in,
output reg valid_out,
output reg ready_out);
reg [5:0] S;
wire S_A, S_B, clkON;
assign S_A = S[1] ^ S[2] ^ S[4] ^S[5];
assign S_B = S[0] ^ S[1] ^ S[2] ^S[5];
assign clkON = clk & !sleep;
always #(posedge clkON)begin
if (reset) begin
S <=0;
valid_out <=0;
ready_out <=0;
end else if (valid_in) begin
out_A <= in_bit ^ S_A;
out_B <= in_bit ^ S_B;
valid_out <=1;
if (ready_in)begin
S<= S<<1;
S[0] <=in_bit;
ready_out <=1;
end else begin
ready_out <=0;
end
end else begin
valid_out <=0;
ready_out <=0;
end
end
endmodule
I am interested to use ready_in flag as an indicator that data out_A and out_B are received by the next block, so my block can accept the new data by setting ready_out flag high. I have written a testbench for this block, however, I am not getting the results I am expecting
`timescale 1 ns/1 ns
module TB_Conv();
reg clk;
//---------------clock generator-----------------------
initial begin
clk = 1'b0;
#5;
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
//------------------ dump -----------------------
initial begin
$dumpfile("dumpVCD.vcd");
$dumpvars(10);
end
localparam N_DATA=10;
reg in_bits_vec [0:N_DATA-1];
initial begin
in_bits_vec[0] = 1'b1;
in_bits_vec[1] = 1'b0;
in_bits_vec[2] = 1'b0;
in_bits_vec[3] = 1'b0;
in_bits_vec[4] = 1'b0;
in_bits_vec[5] = 1'b0;
in_bits_vec[6] = 1'b0;
in_bits_vec[7] = 1'b0;
in_bits_vec[8] = 1'b0;
in_bits_vec[9] = 1'b1;
end
reg in_bit, ready_in,reset, valid_in;
Conv_Encoder_Core UUT(.clk(clk),
.reset(reset),
.in_bit(in_bit),
.out_A(out_A),
.out_B(out_B),
.sleep(1'b0),
.valid_in(valid_in),
.ready_in(ready_in),
.valid_out(valid_out),
.ready_out(ready_out));
//---------------- code starts here -------------------//
reg [3:0] addr;
always #(posedge clk) begin
if (reset)begin
addr<=0;
valid_in <=0;
in_bit <=0;
end else if (addr < 10) begin
in_bit <= in_bits_vec[addr];
valid_in <=1'b1;
if (ready_out) begin
addr <= addr+1'b1;
end
end else begin
in_bit <=0;
valid_in <=0;
end
if (valid_out==1) ready_in <= 1;
else ready_in <= 0;
end
// ----------- reset logic -----------//
reg [3:0] cnt;
initial cnt=0;
always #(negedge clk)begin
if (cnt<5) begin
reset = 1;
cnt=cnt+1;
end else reset =0;
end
initial begin
#1000;
$finish;
end
endmodule
if you look at the input data (in the testbech), you can see it is 1000000000. I am expecting to see 1 being passed through S register as follows:
S = 000000 //at beginning
S = 000001 // after ready_out=1
S = 000010
S = 000100
however, the results I get is entirely different(please see snapshot).
Another problem I have is that inbit=1 continues two clock cycles more than what I expect. in fact when ready_out=1, I expect to see that in_bit becomes zero but this happens two clock cycles later(yellow cursor in the snapshot ).
I would be most grateful if someone could explain what I do wrong in this example.
Conv_Encoder_Core
module Conv_Encoder_Core
(
input wire clk,
input wire reset,
input wire in_bit,
output reg out_A,
output reg out_B,
input wire sleep,
// input channel
input wire inp_valid_i,
output wire inp_ready_o,
// output channel
output reg out_valid_o,
input reg out_ready_i
);
reg [5:0] S;
wire S_A, S_B, clkON;
assign S_A = S[1] ^ S[2] ^ S[4] ^S[5];
assign S_B = S[0] ^ S[1] ^ S[2] ^S[5];
assign clkON = clk & !sleep;
// -- Changes start here -- //
wire wr_en;
reg full_r;
assign wr_en = ~full_r | out_ready_i;
always #(posedge clkON)begin
if (reset) begin
S <=0;
full_r <=0;
end else begin
if (wr_en) begin
if (inp_valid_i) begin
full_r <= 1;
out_A <= in_bit ^ S_A;
out_B <= in_bit ^ S_B;
S <= S<<1;
S[0] <=in_bit;
end else begin
full_r <= 0;
end
end
end
end
assign inp_ready_o = wr_en;
assign out_valid_o = full_r;
endmodule
tb
`timescale 1 ns/1 ns
module tb();
reg clk;
//---------------clock generator-----------------------
initial begin
clk = 1'b0;
#5;
clk = 1'b1;
forever begin
#5 clk = ~clk;
end
end
//------------------ dump -----------------------
initial begin
$dumpfile("dumpVCD.vcd");
$dumpvars(10);
end
localparam N_DATA=10;
reg in_bits_vec [0:N_DATA-1];
initial begin
in_bits_vec[0] = 1'b1;
in_bits_vec[1] = 1'b0;
in_bits_vec[2] = 1'b0;
in_bits_vec[3] = 1'b0;
in_bits_vec[4] = 1'b0;
in_bits_vec[5] = 1'b0;
in_bits_vec[6] = 1'b0;
in_bits_vec[7] = 1'b0;
in_bits_vec[8] = 1'b0;
in_bits_vec[9] = 1'b1;
end
reg in_bit, reset, inp_valid, inp_ready, out_valid, out_ready;
Conv_Encoder_Core UUT(.clk(clk),
.reset(reset),
.in_bit(in_bit),
.out_A(out_A),
.out_B(out_B),
.sleep(1'b0),
// input channel
.inp_valid_i(inp_valid),
.inp_ready_o(inp_ready),
// output channel
.out_valid_o(out_valid),
.out_ready_i(out_ready));
//---------------- code starts here -------------------//
reg [3:0] addr;
// -- Transmitter Side -- //
always #(posedge clk) begin: ff_addr
if (reset)begin
addr <= 0;
end else begin
if (addr < 10) begin
if (inp_valid && inp_ready) begin
addr <= addr + 1;
end
end else begin
addr <= 0;
end
end
end
assign inp_valid = (addr < 10) ? 1'b1 : 1'b0;
assign in_bit = in_bits_vec[addr];
// -- Receiver Side -- //
always #(posedge clk) begin: ff_ready_in
if (reset) begin
out_ready <= 0;
end else begin
out_ready <= $urandom_range(0, 1); // some randomness on the receiver, otherwise, we won't see if our DUT behaves correctly in case of ready=0
end
end
// ----------- reset logic -----------//
reg [3:0] cnt;
initial cnt=0;
always #(negedge clk)begin
if (cnt<5) begin
reset = 1;
cnt=cnt+1;
end else reset =0;
end
initial begin
#1000;
$finish;
end
endmodule
Issues with your implementation
Bad protocol definition & implementation
You are defining a protocol that looks more like "request/acknowledge" than "ready/valid" one, because data transmissions in your protocol are acknowledged after a one-cycle delay. What you need is concurrent transmission acknowledge in the same cycle, something like the following:
A valid data transmission is indicated by the Transmitter through valid=1 and are acknowledged by the Receiver through ready=1. So, a data transmission is valid only when valid && ready in the same cycle. Note that input data is equivalent to in_bit in your case, while output data is out_A and out_B.
Input/Output ready/valid channel confusion
If you add a processing/buffering unit between the Transmitter and the Receiver of the above channel, then what you got is something like this:
In that case, your buffer is the Conv_Encoder_Core module and, apart from its internal core logic, it must expose an input ready/valid channel, from which it receives input data, and an output one, from which it outputs its data. Also note that the Transmitter and the Receiver, are implemented by the testbench code (tb module). See
"Transmitter Side" and "Receiver Side" comments in code.

How to start with zero counter verilog

I'm implementing a repeating bit shifter for a 16 bit number. To do this, I have a bit counter that counts how many times I've shifted and resets when I reach 4'b1111. Then I have an assign statement that feeds the MSB to an output. However, the logic makes it so that the output skips the first MSB every time. What is the most succinct way to include the first MSB, before any shifting has occurred?
CODE
module DAC_Control(
input [15:0]data_in,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
always #(data_in)
shifter <= data_in;
//shifter
always #(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1111) begin
bit_counter <= 4'b0;
enable <= 1'b1;
cs <= 1'b1;
end
else begin //this is the problem area
bit_counter <= bit_counter + 1'b1;
enable <= 1'b0;
cs <= 1'b0;
shifter <= shifter << 1;
end
end
assign data_out = shifter[15];
endmodule
Firstly it would be better to have a trigger to capture the data_in. If not then in simulation ,if the data_in changes in between the shifting it will update the shifter and cause the expected output to change. It would be preferable to capture the data_in based on a qualifying event ( e.g. counter_enable in the example below) . Synthesis will produce an error as shifter has two drivers . One the continuous assignment shifter <= data_in; and other the shifting logic shifter <= shifter << 1;
Updated sample code should serialize the data.
module DAC_Control(
input [15:0]data_in,
input counter_enable,
input clk,
input rst,
output data_out,
output reg cs,
output reg enable
);
//bit counter
reg [3:0] bit_counter;
//to help with shifting
reg [15:0] shifter;
//shifter
always #(posedge (clk)) begin
if (rst) begin
bit_counter <= 4'b0;
shifter <= 0;
end
else if (counter_enable == 1) begin
shifter <= data_in;
bit_counter <= 4'b0;
end
else begin
shifter <= shifter << 1; // shifting
bit_counter <= bit_counter + 1'b1; // counter
end
end
always #(posedge (clk)) begin
if (rst) begin
enable <= 1'b0;
cs <= 1'b1;
end
else if (bit_counter == 4'b1111) begin
enable <= 1'b1;
cs <= 1'b1;
end
else begin
enable <= 1'b0; // generate enable signals
cs <= 1'b0;
end
end
assign data_out = shifter[15];
endmodule

I am unable to write data in an array of type reg. It is default writing xxxx into this

`include "top.v"
`include "c_top.v"
module fixture;
reg [31:0]F[0:100];
reg [31:0]F2[0:50];
reg [31:0]F3[0:50];
reg [31:0]a,b;
reg clk,reset,s;
wire [31:0]r_expected,r_actual;
wire exception_expected,exception_actual;
integer i;
integer j=32;
integer k;
integer m,u;
topdut t1(a,b,s,clk,reset,r_actual,exception_actual);
c_toptest t2(a,b,s,clk,reset,r_expected,exception_expected);
initial
begin
clk = 1'b1;
forever #10 clk = ~clk;
end
//initial
//$monitor($time,"clk=%b reset =%b a=%h b=%h s=%b exception=%b r=%h ",clk,reset,a,b,s,exception,r);
integer ab;
initial
begin
ab=$fopen("input_ab.txt","w");
for(i=0;i<100;i=i+1)
begin
$fdisplay(ab,"%b",$random());
end
$fclose(ab);
end
initial
begin
$readmemb("input_ab.txt",F);
end
always#(posedge clk or negedge reset)
begin
if(!reset)
begin
a <= 32'b0;
b <= 32'b0;
k <= 0;
m <=0;
u <=0;
end
else
begin
a <= F[k];
b <= F[k+50];
k <= k+1;
$display("r is %b and m is %i",r_expected,m);
F2[m] <= r_expected;
m <= m+1;
if(k>=29)
begin
F3[u] <= r_actual;
u <= u+1;
end
end
end
initial
begin
for(i=0;i<100;i = i+1)
begin
$display("c%b c2%b a%b b%b",F2[i],F3[i],F[i],F[i+50]);
end
end
initial
begin
// Initialize Inputs
reset = 1'b0;
#30
reset = 1'b1;
s = 1'b0;
end
initial
begin
#1500 $finish;
end
endmodule
When I display F2[] and F3[] it is taking xxxxxxx.
Even though m and r are having valid values.
Please suggest some solution.
I know there is a small glitch here.
I guess all my declarations are correct.
All my modules are giving correct output from DUT.
Only in this testbench something is wrong
The reg declarations are initialized to x. The display statement executes at time zero before F2 and F3 have been assigned to other values. The correct initial values of x are displayed.

Implementing JK Flipflop in Verilog

I'm trying to implement simple JK Flipflop in Verilog (Modelsim). But I'm getting the following error
The generate if condition must be a constant expression.
Here is the code which I'm using
module jkfflop(J,K,clk,Q);
input J,K,clk;
output Q;
if(J==0 & K==1)
begin
assign Q = 0;
end
else if(J==1 & K==0)
begin
assign Q = 1;
end
else if(J==1 & K==1)
begin
assign Q = ~Q;
end
endmodule
Can someone help me
In Verilog RTL there is a formula or patten used to imply a flip-flop. for a Positive edge triggered flip-flop it is always #(posedge clock) for negative edge triggered flip-flops it would be always #(negedge clock).
An Example of positive edge triggered block.
reg [7:0] a;
always #(posedge clock) begin
a <= b;
end
Normally you want a reset as well, a Synchronous reset would be:
reg [7:0] a;
always #(posedge clock) begin
if ( reset == 1'b1 ) begin
a <= 'b0;
end
else begin
a <= b;
end
end
It is more common is ASIC design to require an active low Asynchronous :
reg [7:0] a;
always #(posedge clock, negedge reset_n) begin
if ( reset_n == 1'b0 ) begin
a <= 'b0;
end
else begin
a <= b;
end
end
Note that the asynchronous reset has reset in the sensitivity list this makes the block respond to changes in the signal.
The way you have used (reused) assign is incorrect.
Using the above info your module would become:
module jkfflop(
input J,
input K,
input clk,
output Q );
always #(posedge clk) begin
if(J==1'b0 && K==1'b1) begin
Q <= 'b0;
end
else if(J==1'b1 && K==1'b0) begin
Q <= 1'b1;
end
else if(J==1'b1 & K==1'b1) begin
Q <= ~Q;
end
end
endmodule
But could be written with a case statement:
always #(posedge clk) begin
case({J,K})
2'b0_0 : Q <= Q ;
2'b0_1 : Q <= 1'b0;
2'b1_0 : Q <= 1'b1;
2'b1_1 : Q <= ~Q ;
endcase
end

Resources