what is wrong with the following code in verilog? - verilog

I am working on rs232 for over one week. My program takes a 13bit dataframe[from testbench] and serially transmits it. Now, I am testing the TX side. I think this[as commented below -here1, here2] is where the problem is.
module rs232_tx(dtr_tx,rts_tx,clk_tx,dsr_tx,cts_tx,data_tx,dataframe_tx,r_tx);
input clk_tx;
input dsr_tx; // data set ready
input cts_tx; // clear to send
//input rx; // not using for now
input r_tx; // asynchronous active low reset signal, given by testbench
input [8:0]data_tx; // send this data serially out, given by testbench
output reg dtr_tx; // data terminal ready
output reg rts_tx; // ready to send
output reg dataframe_tx; // serially out data
reg [1:0]state_tx;
reg [1:0]next_tx;
reg [12:0]temp_tx;
reg done_tx;
reg [3:0]count_tx = 4'b1100; // counting the shift
parameter S_IDLE=2'b00, S_START=2'b01, S_SENDING=2'b10, S_DONE=2'b11, frame_size=4'b1100;
always#(posedge clk_tx, negedge r_tx)
begin
if(~r_tx)
state_tx <= S_IDLE;
else
state_tx <= next_tx;
end
always#(*)
begin
case(state_tx)
S_IDLE:
begin
done_tx = 1'b0;
dtr_tx = 1'b1;
temp_tx = 12'b0;
next_tx = (dsr_tx) ? S_START : S_IDLE; // dsr gives receiver information
end
S_START:
begin // form data-frame
rts_tx = 1'b1;
.
.
.
//assigning data to temp_tx bit by bit. And few more bits.
.
.
next_tx = (cts_tx) ? S_SENDING : S_START;
end
S_SENDING:
begin
//dataframe_tx = temp_tx[frame_size - count_tx];
dataframe_tx = temp_tx[frame_size];
temp_tx = temp_tx<<1;
count_tx = count_tx - 1;
if(|count_tx)
next_tx = S_SENDING;
else
begin
next_tx = S_DONE;
done_tx = 1'b1;
end
end
S_DONE:
begin
done_tx = 1'b0;
end
default:
next_tx = S_IDLE;
endcase
end
endmodule
In the testbench:
module rs232_tb;
.
.
rs232_tx dut(.clk(c_Clock),.rst(c_r),.dataframe_tx(t_data),done_tx,temp_tx);
.
.
.
initial
begin
$dumpfile("rs232.vcd");
$dumpvars(0,rs232_tb);
#7 c_r = 1'b1;
// checking Tx
#7 t_dsr = 1'b1; // Data Set Ready signal for rs232
#7 t_data = 9'b101010101; // data to be transmitted on receiving CTS from RX.
#7 t_cts = 1'b1; // Clear To Send signal from RX
#50 $finish;
end
.
.
.
The problem is, I am always getting temp_tx[12] value on dataframe_tx, and then temp_tx is logically rotated left by one. Next time, this shift is not happening.
I observed the reg [3:0]state it remains on S_SENDING state but there is no logical shift performed on the next clock edge.
Also, as a side note, I observed that count_tx decrements only once and later just remains constant to value 11.
I am in the learning phase. I cannot find any solution on internet or anyone sharing this kind of problem. Please help me...

In sequential process you use next, while in combo U assign to next_tx ?
Also it looks like combo-loop, the counters you use there should be moved to sequential process - you should not use the same signal in LHS and RHS when it’s combinational process.
Search for “combinatorial loop” in google for more details.

You are performing logical operations on temp_tx which is a primary input this is not correct. Store this input to a register and perform operations on it.
always#(posedge clk or negedge rst_n)
begin
if(!rst_n)
temp_tx_reg <= 'd0;
else if (state == S_START) // Register input when initializing
temp_tx_reg <= temp_tx;
end
Also please use a proper always block for counters.
always#(posedge clk or negedge rst_n)
begin
if(!rst_n)
count_tx <= 4'b0000;
else if(state == S_START)
count_tx <= 4'b1100;
else if(state == S_SENDING && |count_tx)
count_tx <= count_tx - 1'd1;
end
I would suggest you follow steps via FSM.
State1 -- Initialize registers and counters.
State2 -- Perform the serialization.
State3 -- Set the output flags.

Related

Implementation of a TDC in System Verilog

I'm attempting to implement a Time to Digital Converter (TDC) in System Verilog. So far I've attempted 2 different methods and not sure if either has been successful.
The First Method is based on the following diagram
'''
module TDC #(
parameter bits = 8
)(
input logic start,
input logic progate_stop,
input logic reset,
output logic [bits-1:0] comb_output
);
logic comb_one, comb_two, comb_three, comb_four, comb_five, comb_six, comb_seven, comb_eight;
logic pipo_one, pipo_two, pipo_three, pipo_four, pipo_five, pipo_six, pipo_seven, pipo_eight;
always_comb begin
comb_one = start;
comb_two = ~comb_one;
comb_three = ~comb_two;
comb_four = ~comb_three;
comb_five = ~comb_four;
comb_six = ~comb_five;
comb_seven = ~comb_six;
comb_eight = ~comb_seven;
end
always_ff#(progate_stop) begin
if (reset ) begin
pipo_one <= 1'b0;
pipo_two <= 1'b0;
pipo_three <= 1'b0;
pipo_four <= 1'b0;
pipo_five <= 1'b0;
pipo_six <= 1'b0;
pipo_seven <= 1'b0;
pipo_eight <= 1'b0;
end else begin
pipo_one <= comb_one;
pipo_two <= comb_two;
pipo_three <= comb_three;
pipo_four <= comb_four;
pipo_five <= comb_five;
pipo_six <= comb_six;
pipo_seven <= comb_seven;
pipo_eight <= comb_eight;
end
end
always_comb begin
comb_output[0] = pipo_one;
comb_output[1] = ~pipo_two;
comb_output[2] = pipo_three;
comb_output[3] = ~pipo_four;
comb_output[4] = pipo_five;
comb_output[5] = ~pipo_six;
comb_output[6] = pipo_seven;
comb_output[7] = ~pipo_eight;
end
endmodule
The second method is based on the following diagram:
module TDC (
output reg [7:0] out , // Output of the counter
input wire enable , // enable for counter
input wire clk , // clock Input
input wire reset, // reset Input
input logic start,
input logic stop
);
//-------------Code Starts Here-------
always_ff #(posedge clk) begin
if (reset) begin
out <= 8'b0 ;
end else begin
if (start && !stop) begin
out <= out+1;
end else begin
out <=out;
end
end
end
endmodule
Any advice on either of these would be greatly appreciated!
Thank you in advanc
a TDC is very dependant on the underlying technology that you are using. Although it is a "digital" block (in the sense that you use digital gates and flops to implement it), the reality is that in order to obtain accurate timings, you need to carefully lay out the gates and the flops, so typically you will need:
a) describe the circuit structurally, using the cells available in your ASIC library/FPGA
b) carefully lay out the elements so that TDC timing measurements are accurate.
In other words, writing behavioural RTL as you're doing is not going to achieve what you want, sorry.

Serial-Load-Shift-Register

In the serial load shift register, how can i make sure that the shift was not disabled before at least five data has been loaded?
module serial_load_shift_register(
input logic clk ,
input logic shift_enable,
input logic d_in ,
output logic q
);
logic [0:4] register;
always #(posedge clk) begin
register[0] <= shift_enable ? d_in : register[0];
register[1] <= shift_enable ? register[0] : register[1];
register[2] <= shift_enable ? register[1] : register[2];
register[3] <= shift_enable ? register[2] : register[3];
register[4] <= shift_enable ? register[3] : register[4];
end
assign q = register[4];
endmodule: serial_load_shift_register
What you can do is put the shift_enable signal into a shift register as well that gives you a history of that signal. If that register is non-zero, use that condition to control the shifting of data.
module serial_load_shift_register(
input logic clk ,
input logic shift_enable,
input logic d_in ,
output logic q
);
logic [0:3] register;
always #(posedge clk) begin
logic [0:4] enable;
enable = {enable,shift_enable};
if (enable != 0) register <= {register, d_in};
end
assign q = register[0];
endmodule: serial_load_shift_register
Note that the assignment to enable is not using an NBA. This means the statements that references enable following the assignment use the current value, not the value from the previous cycle. There are no issues with race conditions because I declared enable local to the always block, so no one can reference it outside the always.
There are several ways to do it. In general you need a kind of a counter which will be used to keep your enable alive for a number of cycles. As an example, you can have another register which shifts the value of the enable signal for 5 cycles or so. Here is an example.
module serial_load_shift_register(
input logic clk ,
input logic reset,
input logic shift_enable,
input logic d_in ,
output logic q
);
logic [4:0] register;
logic [4:0] enable_validator;
always #(posedge clk) begin
if (reset) begin
enable_valida <= 0;
register <= 0;
end
else begin
enable_valid <= (enable_valid << 1) | shift_enable;
if (|enable_valid) begin
register <= (register << 1) | d_in;
end
end
end
assign q = register[4];
endmodule: serial_load_shift_register
In the above example enable_valid is such a register. It keeps enable flag alive while any of its bits is non-zero, allowing the register to keep shifting even if the enable_shift signal disappears.
I did a couple of updates to your code. First, I added a 'reset' which is needed to initialize some values. Also, I replaced your bit-by-bit shift with a shift operator <<.
You just need to figure out timing relation between different signals in your model and tune the code up to your needs.
Here is a sample test bench to quick test of the above.
module tb;
logic clk, reset, shift_enable, d_in, q;
serial_load_shift_register shifter(.clk(clk), .reset(reset), .shift_enable(shift_enable), .d_in(d_in), .q(q));
initial begin
clk = 0;
forever #2 clk = !clk;
end
initial begin
reset = 0;
d_in = 0;
shift_enable = 0;
#4 reset = 1;
#4 reset = 0;
#4 d_in = 1;
#4 shift_enable = 1;
#8 shift_enable = 0;
d_in = 0;
#30 $finish;
end
always #* begin
$display("%0t> clk %b, shift_enable = %b, d_in = %b, q ==> %b (%b %b)", $time, clk, shift_enable, d_in, q,
shifter.enable_validator, shifter.register);
end
endmodule

Verilog Synchronous 4 bit Counter stay on max value until given signal

So I have my counter in verilog which is 4 bits and I want it to stay on max value, 1111, until I give it a signal to start counting from 0000 again.
Here's what I've been able to come up with so far:
module contadorAscMax
(
input iClk,
input iRst,
output oQ,
input iCE,
input iSignal,
output [3:0] orCnt
);
reg[3:0] rvCnt_d;
reg[3:0] rvCnt_q;
assign orCnt = rvCnt_q;
always #(posedge iClk or posedge iRst)
begin
if(iRst)
begin
rvCnt_q<=4'b0;
end
else
begin
if(iCE)
begin
rvCnt_q<=rvCnt_d;
end
else
begin
rvCnt_q<=rvCnt_q;
end
end
end
always #*
begin
rvCnt_d=rvCnt_q+4'b1;
if(rvCnt_d == 4'b1111)
begin
rvCnt_d = rvCnt_d;
end
else if(rvCnt_d == 4'b1111 & iSignal)
begin
rvCnt_d = 4'b0;
end
end
endmodule
But it just won't wait for the signal. I am very new to verilog so my code probable doesn't make much sense to a hardware guy, since I am a software engineer so sorry if there are some rookie mistakes here.
As for the testbench, here is what I have:
`timescale 1ns / 1ps
module vtfContMax;
// Inputs
reg iClk;
reg iRst;
reg iCE;
reg iSignal;
// Outputs
wire oQ;
wire [3:0] orCnt;
// Instantiate the Unit Under Test (UUT)
contadorAscMax uut (
.iClk(iClk),
.iRst(iRst),
.oQ(oQ),
.iCE(iCE),
.iSignal(iSignal),
.orCnt(orCnt)
);
initial begin
// Initialize Inputs
iClk = 1;
iRst = 1;
iCE = 1;
iSignal = 0;
// Wait 100 ns for global reset to finish
#10;
iRst = 0;
repeat(10)
begin
repeat(10)
begin
wait(iClk);
wait(!iClk);
end
end
$stop();
// Add stimulus here
end
always
begin
#5;
iClk = ~iClk;
#10
iSignal = ~iSignal;
end
endmodule
Thanks for any help :)
You have split the code in a register and combinatorial section. Although that is a good idea for complex logic, for a simple 4 bit counter it is a bit over the top.
For solving your problem you are close. The trick with code like this, is to make the definition using 'programming' language. Then the code flows from that.
I want to have a counter which goes from 1111 to 0000 when a signal is present, else I want it to count up.
This then leads to:
always #(clk or posedge reset)
begin
if (reset)
count <= 4'b1111;
else
begin
if (count==4'b1111 && start_signal)
count <= 4'b0000;
else
count <= count + 4'b0001
end
end
What you don't mention, but what I see from your code you also have an enable (iCE) and an unused output oQ. The total then becomes:
module contadorAscMax
(
input iClk,
input iRst,
// output oQ,
input iCE,
input iSignal,
output reg [3:0] orCnt
);
always #(iClk or posedge iRst)
begin
if (iRst)
orCnt <= 4'b0000; // or should that be 4'b1111
// Is this really what you want?
// It will start counting after a reset!
else
begin
if (iCE)
begin
if (orCnt==4'b1111 && iSignal)
orCnt <= 4'b0000;
else
orCnt <= orCnt+ 4'b0001;
end
end
end
endmodule
Some more remarks:
Your reset condition looks flawed to me but you have to solve that.
Give the counter enable signal a decent name: 'count_enable' not 'signal'.
Last: I would not use all the 'i's and 'o's. The 'o' signals from one module will be the 'i' of another. Thus you have to change the signal names somewhere. It is better to have a defined signal in your system. If only so you can find in the timing report or gates after synthesis.

Verilog Reg Array

Having a bit of trouble with looping through a 1D reg array.
ultimately I am trying to accomplish the following.
in "Listen" state, the rx_values fill a read buffer (4 8-bit characters) to store the characters being typed in a console and echo back the character by setting tx_data to the last character (this works)
when the enter key is hit, the state switches to "Read" which sets the tx_data to the readbuffer with each iteration until the 4th character is reached at which time the state is reset to idle. (this doesnt work)
I get to the read state;however,the counter does not work as expected.
any help would be greatly appreciated.
module receiver (
input clk,
input rst,
output reg [7:0] tx_data,
output reg new_tx_data,
input tx_busy,
input [7:0] rx_data,
input new_rx_data
);
localparam idle = 4'h0 ,listen = 4'h1 ,read = 4'h2, write = 4'h3;
reg [3:0] state = idle;
reg [7:0] readbuff[3:0];
integer buffdex;
always #* begin
end
always #(posedge clk) begin
new_tx_data = 1'b0;
case (state)
idle: begin
if(new_rx_data) begin
state<=listen;
end
end
listen: begin
new_tx_data = 1'b1;
readbuff[buffdex] = rx_data;
tx_data = readbuff[buffdex];
//tx_data = buffdex;
buffdex = buffdex + 1';
if(rx_data == 8'h0D) begin
tx_data = "\n";
buffdex = 0;
state <= read;
end else begin
state<=idle;
end
end
read: begin
new_tx_data = 1'b1;
tx_data = readbuff[buffdex];
buffdex = buffdex + 1;
if (buffdex == 3) begin
state <= idle;
end
//tx_data = state;
end
endcase
end
endmodule
Sorry to use "answer" feature instead of comment but I don't have enough points yet. This is intended as a "comment". Since you wanted any help I hope this fits.
1) Your code needs some improvement both in functionality and readability (empty combo blocks, mixing BA with NBA -> mixing combo with sequential logic, reset input but no reset logic, commented logic lines, latches on FSM).
Consider rewriting it according to some good coding practices, e.g. http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
You also have inconsistencies like buffdex = buffdex + 1' and buffdex = buffdex + 1. (And thus doesn't compile on incisive).
2) Can you provide a testbench for this module? Have you tried strobing signals to check their values? Does buffdex increment in read state? Is the if statement reachable?
3) Since this isn't a 1st problem with Mojo (seems like under developement) you may consider free https://www.edaplayground.com/ for both testing and compiling/syntax checking.
So I read the paper (along with other various IEEE instructions) and finally got a working version. below is the code. as before I am open the suggestions as to how the code can be made more efficient or functional. I think the read buffer is one big latch, but not sure how to fix it.
module receiver (
//inputs
input clk,
input rst,
input tx_busy,
input [7:0] rx_data,
input new_rx_data,
//outputs
output reg [7:0] tx_data,
output reg new_tx_data,
output reg [0:4] LED
);
//local parameters
localparam IDLE = 2'b00 , LISTEN = 2'b01 ,NEWLINE = 2'b10, READ = 2'b11;
//fsm state reg and readbuff reg
reg [1:0] stated, stateq;
reg [3:0] cntrd,cntrq;
reg [7:0] readbuff [15:0];
reg nl;
//on clock edge set flip-flop - non-blocking assignments
always #(posedge clk ) begin
if(rst) begin
stateq <= IDLE;
cntrq<=4'b0000;
end else begin
//update the state and readbuff index values to be current.
stateq <= stated;
cntrq <=cntrd;
end
end
//sequential and combinational blocking assignments
always #(*) begin
//set default states to avoid latches.
stated = stateq;
cntrd = cntrq;
LED = cntrq;
//set output defaults
tx_data = 8'hxx;
new_tx_data = 1'b0;
case (stateq)
IDLE: begin
//move to listen state
cntrd=4'b0;
stated = stateq + 1'b1;
end
LISTEN: begin
if(new_rx_data) begin
//set readbuffer[indx] to the rx data
readbuff[cntrq] = rx_data;
new_tx_data = 1'b1;
tx_data = readbuff[cntrq];
cntrd = cntrq + 1'b1;
//if enter is pressed change states, otherwise, echo and increase the read buffer.
if(rx_data == "\r" || rx_data == "\n") begin
stated = stateq + 1'b1;
cntrd=4'b0000;
end
end
end
NEWLINE: begin
if(!tx_busy) begin
new_tx_data = 1'b1;
tx_data = 8'h0A;
nl = 1'b1;
stated = stateq + 1'b1;
end
end
READ: begin
//check the value of cntrq for the enter statement
if(readbuff[cntrq] == "\r" || readbuff[cntrq] == "\n" ) begin
stated = IDLE;
//otherwise write out the value of the readbuff - tx busy should sync to avr clock
end else begin
if (!tx_busy) begin
new_tx_data = 1'b1;
tx_data = readbuff[cntrq];
cntrd = cntrq + 1'b1;
end
end
end
endcase
end
endmodule

How to write a verilog code in two-always-block style with multiple state regs?

I'm a begginer of Verilog. I read a several materials about recommended Verilog coding styles like this paper and stackoverflow's questions.
Now, I learned from them that "two always block style" is recommended; separate a code into two parts, one is a combinational block that modifies next, and the another is a sequential block that assigns it to state reg like this.
reg [1:0] state, next;
always #(posedge clk or negedge rst_n)
if (!rst_n)
state <= IDLE;
else
state <= next;
always #(state or go or ws) begin
next = 'bx;
rd = 1'b0;
ds = 1'b0;
case (state)
IDLE : if (go) next = READ;
else next = IDLE;
...
And here is my question. All example codes I found have only one pair of registers named state and next.
However, if there are multiple regs that preserve some kinds of state, how should I write codes in this state-and-next style?
Preparing next regs corresponding to each of them looks a little redundant because all regs will be doubled.
For instance, please look at an UART sender code of RS232c I wrote below.
It needed wait_count, state and send_buf as state regs. So, I wrote corresponding wait_count_next, state_next and send_buf_next as next for a combinational block. This looks a bit redundant and troublesome to me. Is there other proper way?
module uart_sender #(
parameter clock = 50_000_000,
parameter baudrate = 9600
) (
input clk,
input go,
input [7:0] data,
output tx,
output ready
);
parameter wait_time = clock / baudrate;
parameter send_ready = 10'b0000000000,
send_start = 10'b0000000001,
send_stop = 10'b1000000000;
reg [31:0] wait_count = wait_time,
wait_count_next = wait_time;
reg [9:0] state = send_ready,
state_next = send_ready;
reg [8:0] send_buf = 9'b111111111,
send_buf_next = 9'b111111111;
always #(posedge clk) begin
state <= state_next;
wait_count <= wait_count_next;
send_buf <= send_buf_next;
end
always #(*) begin
state_next = state;
wait_count_next = wait_count;
send_buf_next = send_buf;
case (state)
send_ready: begin
if (go == 1) begin
state_next = send_start;
wait_count_next = wait_time;
send_buf_next = {data, 1'b0};
end
end
default: begin
if (wait_count == 0) begin
if (state == send_stop)
state_next = send_ready;
else
state_next = {state[8:0], 1'b0};
wait_count_next = wait_time;
send_buf_next = {1'b1, send_buf[8:1]};
end
else begin
wait_count_next = wait_count - 1;
end
end
endcase
end
assign tx = send_buf[0];
assign ready = state == send_ready;
endmodule
I think you did a good job and correctly flopped the variables. The issue is that without flops you would have a loop. i.e. if you write something like the following, the simulation will loop and silicon will probably burn out:
always_comb wait_count = wait_count - 1;
So, you need to stage this by inserting a flop:
always_ff #(posedge clk)
wait_count <= wait_count - 1;
Or in your case you you used an intermediate wait_count_next which is a good style:
always_ff #(posedge clk)
wait_count_next <= wait_count;
always_comb
wait_count = wait_count_next;
You might or might not have an issue with the last assignments. Which version of the signals you want to assign to tx and ready? the flopped one or not?
And yes, you can split theses blocks in multiple blocks, but in this case there seems to be no need.
And yes, the other style would be write everything in a single flop always block. But this will reduce readability, will be more prone to your errors and might have synthesis issues.

Resources