one hot encoding in Verilog - verilog

Im just starting to learn how to code in Verilog. Can anyone help me figure out how to implement the following code in verilog using one-hot encoding
module Controller(b, x, clk, rst);
input b, clk, rst;
output x;
reg x;
parameter Off = 2'b00,
On1 = 2'b01,
On2 = 2'b10,
On3 = 2'b11;
reg [1:0] currentstate;
reg [1:0] nextstate;
//state register
always # (posedge rst or posedge clk)
begin
if(rst==1)
currentstate <= Off;
else
currentstate <= nextstate;
end
//combinational
always # (*)
begin
case (currentstate)
Off: begin
x <= 0;
if(b==0)
nextstate <= Off;
else
nextstate <= On1;
end
On1 : begin
x <= 1;
nextstate <= On2;
end
On2 : begin
x <= 1;
nextstate <= On3;
end
On3 : begin
x <= 1;
nextstate <= Off;
end
endcase
end
I tried changing the parameters to:
parameter Off = 4'b0001,
On1 = 4'b0010,
On2 = 4'b0100,
On3 = 4'b1000;
However, ive read that this is not a good implementations.

Some of the advantages of onehot encoding in FSMs are as follows:
Low switching activity. Since only single bit is switched at a time, the power consumption is less and it is less prone to glitches.
Simplified encoding. One can determine the state just by looking at the bit position of '1' in the current state variable.
The disadvantage of this technique is that it requires more number of flops. So, if one has a FSM with 10 different states, one needs 10 flops, while one needs only 4 flops when using decimal encoding.
Coming to your question, it is simple to change to onehot encoded FSM. One needs to implement a case statement based on the position of 1 in the currentstate variable. The code snippet can be implemented as follows:
parameter Off = 2'b00,
On1 = 2'b01,
On2 = 2'b10,
On3 = 2'b11;
//...
always # (*)
begin
nextstate = 4'b0000;
case (1'b1)
currentstate[Off] : begin
x = 0;
if(b==0)
nextstate[Off] = 1'b1;
else
nextstate[On1] = 1'b1;
end
currentstate[On1] : begin
x = 1;
nextstate[On2] = 1'b1;
end
//...
A simple example is available at this link and explanation is over here. Cummings paper is also a good source for more info.
EDIT: As #Greg pointed out, it was a copy-paste error. A combinational block must use blocking assignments.

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.

Is this a true FSM?

I have a conceptual question about FSM's and whether or not the following code is a true FSM. This is for my own curiosity and understanding about the subject. When I wrote this code, I was under the impression that this was an FSM, but now I am not so sure. According to a lot of reading I have done, a TRUE FSM should only consist of a sequential state transition block, followed by either one or two combination blocks to calculate the next state and the output logic.
My current code synthesizes and works on my Basys3 board, so I understand there may be an argument for "if it ain't broke, don't fix it" but it's been bugging me for a while now that I may have an incorrect understanding about how to write an FSM in HDL.
I have tried at least 4 or 5 different ways to rewrite my code using the format mentioned above, but I can't seem to get it without inferring latches, mainly due to the use of a counter, and the fact that pckd_bcd needs to remember its previous value.
Could somebody please explain to me either why this algorithm isn't fit for a true FSM, why it is fit for a true FSM and where my misunderstanding is, or how to rewrite this into the format mentioned above.
module double_dabble #
(
parameter NUM_BITS = 8
)
(
input wire i_clk,
input wire i_rst,
input wire [NUM_BITS-1:0] i_binary,
output wire [15:0] o_pckd_bcd
);
localparam s_IDLE = 3'b000;
localparam s_SHIFT = 3'b001;
localparam s_CHECK = 3'b010;
localparam s_ADD = 3'b011;
localparam s_DONE = 3'b100;
reg [2:0] state;
reg [NUM_BITS-1:0] bin;
reg [3:0] count;
reg [15:0] pckd_bcd;
reg [NUM_BITS-1:0] input_reg;
reg [15:0] output_reg;
assign o_pckd_bcd = output_reg;
always #(posedge i_clk)
begin
if(i_rst)
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
output_reg <= 0;
input_reg <= 0;
end
else
begin
input_reg <= i_binary;
state <= s_IDLE;
// FSM
case(state)
s_IDLE :
begin
state <= s_IDLE;
bin <= 0;
count <= 0;
pckd_bcd <= 0;
if (input_reg!=i_binary)
begin
bin <= i_binary;
state <= s_SHIFT;
end
end
s_SHIFT :
begin
state <= s_CHECK;
bin <= bin<<1;
count <= count+1;
pckd_bcd <= pckd_bcd<<1;
pckd_bcd[0] <= bin[NUM_BITS-1];
end
s_CHECK :
begin
state <= s_ADD;
if(count>=NUM_BITS)
state <= s_DONE;
end
s_ADD :
begin
state <= s_SHIFT;
pckd_bcd[15:12] <= add_three(pckd_bcd[15:12]);
pckd_bcd[11:8] <= add_three(pckd_bcd[11:8]);
pckd_bcd[7:4] <= add_three(pckd_bcd[7:4]);
pckd_bcd[3:0] <= add_three(pckd_bcd[3:0]);
end
s_DONE :
begin
state <= s_IDLE;
output_reg <= pckd_bcd;
end
endcase
end
end
function [3:0] add_three;
input [3:0] bcd;
if (bcd > 4)
add_three = bcd +3;
else
add_three = bcd;
endfunction
endmodule
In general, your code looks like it implements an FSM. You have evidence that the design is working as desired on your board.
The coding style you have chosen (one always block) is a valid Verilog approach. Another common FSM coding style involves two always blocks: one sequential and one combinational. See here for an example. It is not mandatory for an FSM to use two always blocks in Verilog.
One thing that I do notice in your code is that you are making multiple nonblocking assignments to the state signal at the same time. That is unusual.
For example, right before the case statement, you have:
state <= s_IDLE;
Then, in the IDLE case-item, you have the same code:
state <= s_IDLE;
I recommend trying to clean that up by adding a default to the case statement. A default is also a good coding practice when you have some undefined states, as in your FSM. You have only defined 5 of the 8 possible states (state is a 3-bit register).
Another example of multiple nonblocking assignments is:
s_CHECK :
begin
state <= s_ADD;
if(count>=NUM_BITS)
state <= s_DONE;
end
That would be better coded as:
s_CHECK :
begin
state <= (count>=NUM_BITS) ? s_DONE : s_ADD;
end
Following recommended coding practices yields more predictable simulation and synthesis results.

SIPO (Serial Input Parallel Output) FSM synthesis problem

I want to write a Serial to Parallel conversion in Verilog, and I can't realize what is wrong with my code. It doesn't synthesize, and not even the ISE shows what the problem is. Can anyone help me?
I guess the problem is around the second always block. The part:
if (STATE == TRANSMIT)
PAR_OUT[COUNTER] = SER_IN;
seems wrong to me, but I can't understand what to change or test.
module SIPO(
input SER_IN,
input RST,
input CLK,
input LOAD,
output reg READY,
output reg [7:0] PAR_OUT
);
parameter IDLE = 2'b00, START = 2'b01, TRANSMIT = 2'b10, STOP = 2'b11;
reg [1:0] STATE;
reg [2:0] COUNTER;
always # ( posedge CLK or negedge RST)
if (~RST)
begin
STATE <= IDLE;
READY <= 1;
COUNTER <= 0;
end
else
begin
if (STATE == IDLE)
begin
READY <= 1;
COUNTER <= 0;
if (LOAD)
begin
STATE <= START;
end
else
STATE <= IDLE;
end
else
if (STATE == START)
STATE <= TRANSMIT;
else
if (STATE == TRANSMIT)
begin
COUNTER <= COUNTER + 1;
if (COUNTER == 7)
STATE <= STOP;
end
else
begin
STATE <= IDLE;
READY <= 1;
end
end
always #( * )
begin
if (STATE == IDLE)
PAR_OUT = 1;
else
if (STATE == START)
PAR_OUT = 0;
else
if (STATE == TRANSMIT)
PAR_OUT[COUNTER] = SER_IN;
else
PAR_OUT = 1;
end
endmodule
I think your suspicion might be correct regarding PAR_OUT[COUNTER]. When I synthesize your code on edaplayground with Yosys, it infers latches for PAR_OUT, which you likely do not want.
PAR_OUT is 8 bits wide, but you only assign 1 of the 8 bits at a time in the TRANSMIT state, which means the other 7 bits retain their state. For example, if COUNTER=3, then only PAR_OUT[3] is assigned.
I recoded your combo logic, simplifying it with a case statement to make the issue more evident (it should be functionally equivalent to your if/else code):
always #* begin
case (STATE)
TRANSMIT: PAR_OUT[COUNTER] = SER_IN; // Assign to only 1 bit <---
START : PAR_OUT = 8'h00; // Assign to all 8 bits
default : PAR_OUT = 8'h01; // Assign to all 8 bits
endcase
end
If you can afford one cycle of latency, you could use sequential logic for PAR_OUT, such as a shift register.

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.

I want to implement a circuit in my DE1-SOC based on the SDRAM, where should I start? (I already finished a part)

I want to make a simple project on which I load 10 numbers in SDRAM of my Altera DE1-SOC ready to be taken as input for a Logic Unit I am creating,
the logic unit only does a simple arithmetic " Y =(X+1)*(X-1), X is the input and Y is the output ".It will pick the values (one by one) from the SDRAM, calculate and spit out the result in another SDRAM arrangement.
Then the SDRAM should store this data, I wish to take this data out of the DE1-SOC to a PC, for example.
Until now I've done this code, (in case is necessary to check):
module mem_prue1 (rst_n, clk, fin);
input clk, rst_n;
output fin;
wire [6:0] data_X;
reg [6:0] sec_A, sec_B, s_sec_A, s_sec_B;
reg [13:0] rslt_Y, s_rslt_Y;
reg save_sec_A, save_sec_B, save_rslt_Y, set_ram;
reg clear, enable, next_num, no_num, fin, w_mem_out;
reg [1:0] state, nextstate;
reg [3:0] indx;
parameter S0 = 0; parameter S1 = 1; parameter S2 = 2; parameter S3 = 3;
RAM_IN RAM_IN_inst1 (
.data_X (data_X),
.indx(indx)
);
RAM_OUT RAM_OUT_inst1 (
.s_rslt_Y (s_rslt_Y),
.w_mem_out (w_mem_out),
.set_ram (set_ram)
);
always # (posedge clk or negedge rst_n)
begin
if (~rst_n)
begin
set_ram <= 1;
indx <= 0;
no_num <=0;
enable <= 1;
s_sec_A <= 0;
s_sec_B <= 0;
s_rslt_Y <= 0;
state <= S0;
end
else if (clear)
begin
enable <= 0;
state <= nextstate;
no_num <= 0;
indx <= 0;
set_ram <= 1;
fin <= 1;
end
else
begin
set_ram <= 0;
state <= nextstate;
if (save_sec_A)
s_sec_A <= sec_A;
if (save_sec_B)
s_sec_B <= sec_B;
if (save_rslt_Y)
s_rslt_Y <= rslt_Y;
if (next_num)
begin
if (indx >= 9)
begin
indx <= 0; /// resetea el indice de la memoria
no_num <= 1; // se informa que no hay numeros
end
else
indx <= indx + 4'b0001;
end
end
end
always # (*)
begin
w_mem_out = 0;
sec_A = 0; sec_B = 0; rslt_Y = 0;
save_sec_A = 0; save_sec_B = 0;
save_rslt_Y = 0; clear = 0;
next_num = 0;
case (state)
S0:
begin
if (~enable)
nextstate = S0;
else
begin
sec_A = data_X + 7'b0000001;
save_sec_A = 1;
nextstate = S1;
end
end
S1: begin
sec_B = data_X - 7'b0000001;
save_sec_B = 1;
nextstate = S2;
end
S2: begin
rslt_Y = s_sec_A * s_sec_B;
save_rslt_Y = 1;
nextstate = S3;
end
S3: begin
w_mem_out = 1;
next_num = 1;
nextstate = S0;
if (no_num == 1)
clear = 1;
end
default:
nextstate = S0;
endcase
end
endmodule
This is the memory I "simulated" as a RAM for input data :
module RAM_IN (data_X, indx);
input [0:3] indx;
output [6:0] data_X;
reg [6:0] data_X;
reg [6:0] in_ram [0:9];
always # (indx)
data_X = in_ram [indx];
initial
begin
$readmemb("C:/altera/15.0/PROYECTOS/mem_prue/in_ram.txt", in_ram);
end
endmodule
and this for output data:
module RAM_OUT (s_rslt_Y, w_mem_out, set_ram);
input [13:0]s_rslt_Y;
input set_ram, w_mem_out;
reg [3:0] addr_out; // tamano de 57600 datos
reg [13:0] mem_out [0:9];
always # (w_mem_out or set_ram)
begin
if (set_ram)
addr_out = 0;
else if (w_mem_out == 1)
begin
mem_out [addr_out] = s_rslt_Y;
addr_out = addr_out + 4'b0001;
end
else
addr_out = addr_out;
end
endmodule
and The test bench:
module mem_prue1_tb ();
wire fin;
reg clk, rst_n;
mem_prue1 mem_prue1_inst1 (
.clk(clk),
.rst_n (rst_n),
.fin (fin)
);
initial
begin
rst_n <= 1;
#1 rst_n <= 0;
#2 rst_n <= 1;
clk <= 1;
end
always
begin
#5 clk = ~clk;
end
//---------------------------
integer out,i;
initial begin
out=$fopen("C:/altera/15.0/PROYECTOS/mem_prue/mem_out.txt");
end
always#(posedge clk) begin
if(fin==1)
for(i=0;i<=9;i=i+1) begin
$fdisplay(out,"%b",mem_prue1_inst1.RAM_OUT_inst1.mem_out[i]);
if(i==9)begin
$stop;
end
end
end
endmodule
So, basically now I want to substitute that "simulated" RAM for real SDRAM, I don't know what is the most practical way to do it.
Should I use QSYS, NIOS-II, or only by learning the Megawizard IP library and generating a variation of the UniPHY. I'm just learning to use the FPGA, so I'm kinda confused at this part. I want to download the proper manuals and tutorials for learn this in detail but I wish you guys could orient me.
PD: My target would be to "isolate" my logic unit from the "simulated ram" because I'm guessing if I program just like I did, it will consume logic resources and my main goal is to calculate the Area, Energy and Speed consumption of my logic ONLY, without the memory burden.
Thanks.
Your keywords, (QSYS, megawizard, uniphy) indicate Altera. If you are just going to simulate the SDRAM, you should be okay. Sometimes, bringing up that interface in a real chip gets hairy the first time.
If you are just doing simulation, I would use QSYS to generate the SDRAM controller module. If you can do DDR3, that there is the ability to generate an Example Design. If you do that, you will be able to see how the interface to the DDR3 works. In fact it should be already to go.
As an FYI, there will be more latency on the read though, so you need to be able to either wait for the response, or you need to have a pipeline architecture, where you can have multiple reads in flight simultaneously.
The "FPGAs Now What?" tutorial offers some advice (for a Xilinx platform, which apparently doesn't match your particular case) on SDRAM simulation. Basically, it boils down to finding an SDRAM vendor with an available Verilog/VHDL model, and plugging it in to a simulation testbench. (Note that these models aren't going to be synthesizeable.)
http://www.xess.com/static/media/appnotes/FpgasNowWhatBook.pdf
Altera has a tutorial for connecting the SDRAM to a Nios II system (using Qsys) on the DE1-SoC board.
ftp://ftp.altera.com/up/pub/Altera_Material/16.0/Tutorials/Verilog/DE1-SoC/Using_the_SDRAM.pdf
If you're implementing your own controller (or using a HW only IP Core), the tutorial also has the timing information for the SDRAM as well.

Resources