Verilog Array Walkthrough - verilog

I am just starting Verilog, and with little to no direction. I have been trying to build an 4 bit array that I want to walk through turning on and then off each of my LED's in order. I want them to go from 0-3, 7-4 and start over. I haven't set up my loops yet, however I want to see if I'm at least going in the right direction.
// 4 bit oscillating LED pattern
module count_osc (rstn, osc_clk, clk, LED);
input rstn;
output osc_clk;
output clk;
output [7:0] LED;
reg [22:0]c_delay;
genvar i;
genvar j;
GSR GSR_INST (.GSR(rstn)); // Reset occurs when argument is active low.
OSCC OSCC_1 (.OSC(osc_clk));
generate
for (i=0; i<4; i=i+1) begin : LED_loop
assign LED[i] = (clk);
for (j=4; j<8; j=j+1) begin : LED_loop_2
assign LED[j] = (~clk);
end
end
endgenerate
// The c_delay counter is used to slow down the internal oscillator (OSC) output
// to a rate of approximately 0.5 Hz
always #(posedge osc_clk or negedge rstn)
begin
if (~rstn)
c_delay <= 32'h0000;
else
c_delay <= c_delay + 1;
end
assign clk = c_delay[22];
endmodule

There are few misconceptions about verilog here, which are quite common for programmers coming from more procedural languages.
If your not aware Verilog describes hardware and therefore everything can happen in parallel, we do not procedurally start at the top and work our way through lines of code. Every initial and always blocks are running at the same time.
assign should be used outside of loops and it is a continuos assignment, ie combinatorial logic.
generate is used for parameterising hardware instances, you should not need this on basic examples. NB it also means that the hardware you describe can be quite tricky to understand.
With that in mind you may realise that this block:
generate
for (i=0; i<4; i=i+1) begin : LED_loop
assign LED[i] = (clk);
for (j=4; j<8; j=j+1) begin : LED_loop_2
assign LED[j] = (~clk);
end
end
endgenerate
Does not mean much, the first section is:
assign LED[0] = (clk);
assign LED[1] = (clk);
assign LED[2] = (clk);
assign LED[3] = (clk);
The second for loop is inside the first but only uses the second variable essentially overwriting the same statements 4 times:
assign LED[4] = (~clk);
assign LED[5] = (~clk);
assign LED[6] = (~clk);
assign LED[7] = (~clk);
When suggesting you write out what you want I was implying you write out the above instead of using generates.
Solution
I am not sure of the exact sequence you want from your question as you refer to a 4 bit array but uses 8 elements for the LED.
I think this might be a good place to practice creating a FSM (Finite state machine).
reg [2:0] state;
reg [2:0] nextstate;
always #(posedge clk or negede rst_n) begin
if (~rst_n) begin
state <= 'b0;
end
else begin
state<= nextstate;
end
end
//Next state logic (keeping it simple)
always #* begin
nextstate = state +1;
end
//Output logic
always #* begin
case(state)
3'd0 : LED = 'b0000_0000; //Binary makes sense as we can see the LED pattern
3'd1 : LED = 'b0000_0001;
3'd2 : LED = 'b0000_0011;
3'd3 : LED = 'b0000_0111;
3'd4 : LED = 'b0000_1111;
3'd5 : LED = 'b0000_0111;
3'd6 : LED = 'b0000_0011;
3'd7 : LED = 'b0000_0001;
default : LED = 'b0000_0000; //Default unreachable if we completed the case
endcase
end
I do not think this completes the sequence your trying to do but it should give enough of an understanding to complete the sequence yourself.

Related

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.

Verilog How to change wire by bit with clock?

module clks(
input clk,
output [15:0] led
);
wire div2, div4, div8;
reg [2:0] count = 0;
assign div2 = count[0];
assign div4 = count[1];
assign div8 = count[2];
always #(posedge clk) count = count + 1;
endmodule
How can I turn on each led (I have 15 leds) using clock?
I'm really having trouble finding helpful resources online
initial begin
case({count})
2'b00:
led = 15'b000000000000001;
2'b01:
led = 15'b000000000000010;
...
endcase
end
This didn't work.
Or could I do something like this?
led = led + 1;
In your sample code above, you defined count as 3 bits, but your case statements are 2 bits wide. Also, you don't want the initial statement, rather use an always statement.
always # (count)
begin
case(count)
3'b000 : led = 15'b000_0000_0001;
3'b001 : led = 15'b000_0000_0010;
...
endcase
end
I guess that 'by using clock' means changing the led every clock cycle, right? Also it looks like you are trying to encode the led sequentially. In this case you can do the following:
you need to reset your lead to an initial value, sey 15'b1;
every clock cycle you can just shift it left by one. You should not do it in an initial block (though there is a technical way to do so). Use always blocks:
Here is an example:
module clks(
input clk,
input reset,
output reg [15:0] led
);
always #(posedge clk) begin
if (reset == 1)
led <= 15'b1;
else
led <= led << 1;
end
endmodule
In the above case '1' will travel through all bits of led over 15 clock cycles once. 'led' will become '0' after this. You have to make sure that it becomes '1' again if you want to continue in cycles.
Another possibility is to initialize 'led' in the always block, but it is not always synthesizable. YOu do not need a reset signal here.
initial led = 15'b1;
always #(posedge clk) led <= led << 1;

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.

I2S Transmitter Verilog Implementation not working

I am trying to implement the I2S Transmitter in verilog. The datasheet for it is at: https://www.sparkfun.com/datasheets/BreakoutBoards/I2SBUS.pdf
I wrote the code, but my SD line is delayed 1 clock cycle when i test it.
Can someone check my implementation?
module Transmiter(
input signed [23:0] DLeft, input signed [23:0] DRight, input WS, input CLK,
output reg SD
);
wire PL;
reg Q1,Q2;
reg [23:0] shift_reg;
reg [23:0] Tdata;
assign PL = Q1^Q2;
always #(posedge CLK)
begin
Q1 <= WS;
Q2 <= Q1;
end
always #( Q1) begin
if (Q1)
begin
Tdata <= DRight;
end
else
begin
Tdata <= DLeft;
end
end
always #(negedge CLK)
begin
if(PL)
begin
shift_reg <= Tdata;
end
else begin
SD <= shift_reg[23];
shift_reg <= {shift_reg[22:0],1'b0};
end
end
endmodule
EDIT: here is a image of waveform image
TEST BENCH CODE:
module Transmitter_tb(
);
reg CLK, WS;
reg [23:0] dataL;
reg [23:0] dataR;
wire SDout;
Transmiter UT(dataL, dataR, WS, CLK, SDout);
initial begin
dataL = 24'hF0F0FF; #2;
dataR = 24'h0000F0; #2;
end
always begin
CLK=0; #20;
CLK=1; #20;
end;
always begin
WS=0; #1000;
WS=1; #1000;
end;
endmodule
Your negedge block contains an if-else construct and will only ever compute one or the other on a single clock edge. SD will therefore not change value when PL is high.
Furthermore you are using non-blocking assignments(<=) in your code. This roughly means that changes won't be evaluated until the end of the always block. So even if SD <= shift_reg[23] after shift_reg <= Tdata it will not take on the new value in shift_reg[23] but use the previous value. If you want SD to change immediately when shift_reg[23] changes you need to do this combinatorically.
This should work:
always #(negedge CLK)
begin
if(PL)
begin
shift_reg <= Tdata;
end
else
shift_reg <= {shift_reg[22:0],1'b0};
end
assign SD = shift_reg[23];
Working example: https://www.edaplayground.com/x/4bPv
On a side note I am still not convinced that DRight and DLeft are in fact constants, I can see that they are in your TB but it doesn't make sense that the data for your I2S is constant. Your current construct will probably generate a latch(instead of a MUX), and we generally don't want those in our design.
You should clean up your use of blocking versus non-blocking statements:
Always use non-blocking assigments, meaning "<=", in clocked statements.
Always use blocking assigments, meaning "=", in combinational (non-clocked) statements.
This is a industry-wide recommendation, not a personal opinion. You can find this recommendation many places, see for instance:
http://web.mit.edu/6.111/www/f2007/handouts/L06.pdf
The sensitivtity list being incomplete (as pointed out by #Hida) may also cause issues.
Try to correct these two things, and see if it starts working more as expected.
Also note that you are using Q1 (among other signals) to generate your PL signal. If the WS input is not synchronous to your local clock (as I assume it is not), you need to put one more flop (i.e. two in series) before starting to use the output, to avoid metastability-issues. But you won't see this in an RTL simulation.

Is there a way to sum multi-dimensional arrays in verilog?

This is something that I think should be doable, but I am failing at how to do it in the HDL world. Currently I have a design I inherited that is summing a multidimensional array, but we have to pre-write the addition block because one of the dimensions is a synthesize-time option, and we cater the addition to that.
If I have something like reg tap_out[src][dst][tap], where src and dst is set to 4 and tap can be between 0 and 15 (16 possibilities), I want to be able to assign output[dst] be the sum of all the tap_out for that particular dst.
Right now our summation block takes all the combinations of tap_out for each src and tap and sums them in pairs for each dst:
tap_out[0][dst][0]
tap_out[1][dst][0]
tap_out[2][dst][0]
tap_out[3][dst][0]
tap_out[0][dst][1]
....
tap_out[3][dst][15]
Is there a way to do this better in Verilog? In C I would use some for-loops, but that doesn't seem possible here.
for-loops work perfectly fine in this situation
integer src_idx, tap_idx;
always #* begin
sum = 0;
for (scr_idx=0; src_idx<4; src_idx=scr_idx+1) begin
for (tap_idx=0; tap_idx<16; tap_idx=tap_idx+1) begin
sum = sum + tap_out[src_idx][dst][tap_idx];
end
end
end
It does unroll into a large combinational logic during synthesis and the results should be the same adding up the bits line by line.
Propagation delay from a large summing logic could have a timing issue. A good synthesizer should find the optimum timing/area when told the clocking constraint. If logic is too complex for the synthesizer, then add your own partial sum logic that can run in parallel
reg [`WIDHT-1:0] /*keep*/ partial_sum [3:0]; // tell synthesis to preserve these nets
integer src_idx, tap_idx;
always #* begin
sum = 0;
for (scr_idx=0; src_idx<4; src_idx=scr_idx+1) begin
partial_sum[scr_idx] = 0;
// partial sums are independent of each other so the can run in parallel
for (tap_idx=0; tap_idx<16; tap_idx=tap_idx+1) begin
partial_sum[scr_idx] = partial_sum[scr_idx] + tap_out[src_idx][dst][tap_idx];
end
sum = sum + partial_sum[scr_idx]; // sum the partial sums
end
end
If timing is still an issue, then you have must treat the logic as multi-cycle and sample the value some clock cycles after the input changed.
In RTL (the level of abstraction you are likely modelling with your HDL), you have to balance parallelism with time. By doing things in parallel, you save time (typically) but the logic takes up a lot of space. Conversely, you can make the adds completely serial (do one add at one time) and store the results in a register (it sounds like you want to accumulate the total sum, so I will explain that).
It sounds like the fully parallel is not practical for your uses (if it is and you want to rewrite it, look up generate statements). So, you'll need to create a small FSM and accumulate the sums into a register. Here's a basic example, which sums an array of 16-bit numbers (assume they are set somewhere else):
reg [15:0] arr[0:9]; // numbers
reg [31:0] result; // accumulated sum
reg load_result; // load signal for register containing result
reg clk, rst_L; // These are the clock and reset signals (reset asserted low)
/* This is a register for storing the result */
always #(posedge clk, negedge rst_L) begin
if (~rst_L) begin
result <= 32'd0;
end
else begin
if (load_result) begin
result <= next_result;
end
end
end
/* A counter for knowing which element of the array we are adding
reg [3:0] counter, next_counter;
reg load_counter;
always #(posedge clk, negedge rst_L) begin
if (~rst_L) begin
counter <= 4'd0;
end
else begin
if (load_counter) begin
counter <= counter + 4'd1;
end
end
end
/* Perform the addition */
assign next_result = result + arr[counter];
/* Define the state machine states and state variable */
localparam IDLE = 2'd0;
localparam ADDING = 2'd1;
localparam DONE = 2'd2;
reg [1:0] state, next_state;
/* A register for holding the current state */
always #(posedge clk, negedge rst_L) begin
if (~rst_L) begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
/* The next state and output logic, this will control the addition */
always #(*) begin
/* Defaults */
next_state = IDLE;
load_result = 1'b0;
load_counter = 1'b0;
case (state)
IDLE: begin
next_state = ADDING; // Start adding now (right away)
end
ADDING: begin
load_result = 1'b1; // Load in the result
if (counter == 3'd9) begin // If we're on the last element, stop incrementing counter, we are done
load_counter = 1'b0;
next_state = DONE;
end
else begin // Otherwise, keep adding
load_counter = 1'b1;
next_state = ADDING;
end
end
DONE: begin // finished adding, result is in result!
next_state = DONE;
end
endcase
end
There are lots of resources on the web explaining FSMs if you are having trouble with the concept, but they can be used to implement your basic C-style for loop.

Resources