Verilog Inter-FPGA SPI Communication - verilog

I am trying to communicate between two Xilinx Spartan 3e FPGAs using SPI communication and GPIO pins. The goal is to have a master-slave communication working but for now I am just sending data from Master to Slave and trying to see if the data received is correct.
This is the Master code that sends 16 bits of data to Slave in serial format. After checking on the scope numerous times it seems correct.
module SPI_MASTER_SEND(
input CLK_50MHZ,
input [1:0] ID_user,
input [15:0] DATA_TO_SEND,
output reg SData,
output SCLK,
output notCS
);
parameter max = 20; // max-counter size
reg [6:0]div_counter;
wire [6:0] data_count;
assign data_count[6:0] = div_counter[6:0];
reg CLOCK;
reg Clk_out;
reg CompleteB;
//have the notCS be low for 20 pulses, and hi for 20 pulses.
//sends 16 bits of data during low pulse
always#(posedge CLOCK) begin
if (div_counter == max-1)
begin
div_counter <= 0;
Clk_out <= ~Clk_out;
end
else
begin
div_counter <= div_counter + 1;
end
end
assign notCS = Clk_out;
reg flag;
assign SCLK = flag&&CLOCK; //Clock when notCS is down for 16 pulses
always #(posedge CLOCK) // Parallel to Serial
begin
if (data_count >= 7'd3 && data_count < 7'd18 && notCS ==0)
begin
SData <= DATA_TO_SEND[18-data_count];
flag <=1;
CompleteB<=0;
end
else if (data_count == 7'd18 && notCS ==0)
begin
flag <=1;
SData<=DATA_TO_SEND[0];
CompleteB<=1;
end
else
begin
CompleteB<=0;
flag<=0;
SData <= 0;
end
end
endmodule
This is the code on the Slave receiving end, I check the data on the falling edge of the clock (have tried posedge too) to avoid any timing conflicts.
The Clock,notCS, and SI (serial in) are all coming from the master via gpio pins
module SPI_COMM_SLAVE(CLK,SI,notCS,outputPO,ID_user);
input CLK,SI,notCS;
input [1:0] ID_user;
reg [15:0] PO;
output reg [15:0] outputPO;
reg CompleteB;
reg C;
reg [5:0] cnt;
initial cnt[5:0] = 6'b000000;
always#(negedge CLK)
begin
if (cnt < 6'd15)
begin
PO[15-cnt] <= SI;
cnt <= cnt + 1'b1;
CompleteB<=0;
end
else if (cnt == 6'd15)
begin
PO[0] <= SI;
cnt<=6'b000000;
CompleteB <=1;
end
else
begin
cnt <= cnt;
CompleteB<=0;
end
end
always#(*)begin
if(CompleteB == 1)
outputPO[15:0] <= PO[15:0];
else
outputPO[15:0]<=outputPO[15:0];
end
endmodule
After outputting the "outputPO" to the DAC it gives a bunch of garbage and is clearly not a single value.
Thank you

To debug an FPGA problem like this you should absolutely simulate the design. If you have not already, create a testbench to initiate a write in the master module and connect the slave module as it would be in the system. Check the wave forms match the behavior you expect. It is not effective debugging in hardware until this simulation is working. If you do not have access to a paid simulator there are free verilog simulators available. One suggestion is to build this simulation environment in EDA Playground and then you can share it here as part of the problem description.
Secondly I noticed a number of things that could be improved the quality and readability of your code which does make debugging easier:
Indent code inside blocks (begin/end pairs, etc).
Always use non-blocking assignments inside clocked processes and blocking assignments in combinatorial blocks. For example the non-blocking statements in your combinatorial process assigning outputPO in SPI_COMM_SLAVE are wrong. This can lead to simulation not matching synthesized results.
Latches are not recommended for fpga designs. SPI_COMM_SLAVE will synthesize a 16bit latch for outputPO. Consider making this signal a register.
Your master architecture looks more complex than it needs to be. Consider separating the functionality that initiates the spi transactions (div_counter) from the logic that does the actual spi transaction.

Related

Verilog code that copies an input square wave signal to an output signal?

I was wondering if someone may be able to help me? I was not sure how to word the question, but I am basically trying to write a program that generates a square wave output signal from a square wave input signal, matching the duty cycle and frequency of the input signal. Basically, the output just copies the input. To summarize what I am saying graphically, here is a picture I made:
Link to diagram
It is not my final goal, but it would be enough to get me going. I am having a very hard time figuring out how to work with inputs. I have a signal generator making the input square wave signal, and am sending it into an input pin. I've tried calculating the duty cycle mathematically, and then just trying to assign the output to a reg that is set equal to the input on every rising edge of the clock signal but it didn't work.
Here's my code. It has extra functionality of generating a 1 Hz signal, but that is only from learning earlier how to create the pwm. You can ignore "pwm_reg" and the "pwm" output. The "pwm2" output is intended to copy "apwm" input:
`timescale 1ns / 1ps
module duty_cycle_gen(
input clk,
input rst_n,
input apwm,
output pwm,
output pwm2
);
// Input clock is 250MHz
localparam CLOCK_FREQUENCY = 250000000;
// Counter for toggling of clock
integer counter = 0;
reg pwm_reg = 0;
assign pwm = pwm_reg;
reg apwm_val;
always #(posedge clk) begin
if (!rst_n) begin
counter <= 8'h00;
pwm_reg <= 1'b0;
end
else begin
apwm_val <= apwm;
// If counter is zero, toggle pwm_reg
if (counter == 8'h00) begin
pwm_reg <= ~pwm_reg;
// Generate 1Hz Frequency
counter <= CLOCK_FREQUENCY/2 - 1;
end
// Else count down
else
counter <= counter - 1;
end
$display("counter : %d", counter);
end
assign pwm2 = apwm_val;
endmodule
Here is a simple example with a test bench. (I like to use a small delay when assigning, #1, to help capture causality for debugging purposes):
module example(
input wire clk,
input wire in,
output reg out);
always #(posedge clk)
begin
out <= #1 in;
end
endmodule // example
module example_test();
reg chip__clk;
reg chip__in;
wire chip__out;
reg [10:0] count;
example ex(
chip__clk,
chip__in,
chip__out);
initial
begin
$dumpvars();
count <= #1 0;
end
always #(count)
begin
count <= #1 (count + 1);
if (count == 1000)
begin
$display("RESULT=PASS:0 # done");
$finish_and_return(0);
end
if ((count == 60) & (chip__out != 1))
begin
$display("RESULT=FAIL:1 # chip.out not raised");
$finish_and_return(1);
end
if ((count == 30) & (chip__out != 0))
begin
$display("RESULT=FAIL:1 # chip.out not lowered");
$finish_and_return(1);
end
chip__in <= #1 count[5];
chip__clk <= #1 count[1];
end
endmodule // example_test
It works by treating the in signal as something that can can be thought of as constant over the timescale of the higher frequency clk.
If your in clock is an external signal which might be noisy, with the small latency delay, you can attempt to stabilize it by using a small fifo running with the high frequency clk:
module example(
input wire clk,
input wire in,
output reg out);
reg [1:0] buffer;
always #(posedge clk)
begin
out <= #1 buffer[1];
buffer[1] <= #1 buffer[0];
buffer[0] <= #1 in;
end
endmodule // example

How to synthesis the verilog code using memories inside combinational logic .?

I use the buffers inside Verilog code combinational logic, I'm trying to synthesis the Verilog code using the spyglass synthesis tool. but I'm not able to do it.
Showing
Error : latch inferred for signal buffer A, buffer B.
I attach my Verilog code below, can anyone help me how to solve the problem.
Thank you
Here is my code :
module FIFObuffer (Clk,Reset,Enable, dataIn,dataOut);
input Clk,Reset,Enable;
input signed[16:0]dataIn;
output reg [16:0]dataOut;
//internal registers
reg signed [16:0]data_1;
reg [16:0] A[0:107]; //
Circular buffers A & B
reg [16:0] B[0:107];
reg [16:0]Counter = 0;
reg [16:0]writecount = 0;
reg [16:0]readcount = 1;
reg signed [16:0]C_A;
reg signed [16:0]C_B;
always#(*)begin
if (Enable)begin
A[writecount] = dataIn;
//Circular buffer
B[writecount] = Counter+1;
C_A = A[writecount];
C_B = B[writecount];
writecount = writecount+1;
Counter=0;
end
else begin
A[writecount] = dataIn;
//Circular buffer
B[writecount] = Counter+1;
C_A = A[writecount];
C_B = B[writecount];
writecount = writecount+1;
Counter=0;
end
end module
The reason you're getting inferred latches is because you're not using your provided clock. Clocked memory becomes registers or RAMs, unclocked memory is a latch. Your always block is currently combinational because it's an always#(*) which means "run this code any time any of the inputs changes." Instead, you want a clocked block: always#(posedge Clk) which runs any time there's a positive edge on Clk. Memory that changes on a clock edge is a register or RAM.
Example:
always#(posedge Clk) begin
if (Reset) begin //positive, synchronous reset
//reset your counters to zero
Counter <= 0;
ReadCounter <= 0;
WriteCounter <= 0;
end else begin //your functional code starts here, I just copied yours in with minor changes
if (Enable)begin
A[WriteCounter] <= dataIn; //note the use of delayed (<=) assignments - these are necessary when creating clocked logic
//etc. etc.
end
end
end

Verilog: wait for module logic evaluation in an always block

I want to use the output of another module inside an always block.
Currently the only way to make this code work is by adding #1 after the pi_in assignment so that enough time has passed to allow Pi to finish.
Relevant part from module pLayer.v:
Pi pi(pi_in,pi_out);
always #(*)
begin
for(i=0; i<constants.nSBox; i++) begin
for(j=0; j<8; j++) begin
x = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
pi_in = 8*i+j;#1; /* wait for pi to finish */
PermutedBitNo = pi_out;
y = PermutedBitNo>>3;
tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
end
end
state_out = tmp;
end
Modllue Pi.v
`include "constants.v"
module Pi(in, out);
input [31:0] in;
output [31:0] out;
reg [31:0] out;
always #* begin
if (in != constants.nBits-1) begin
out = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out = constants.nBits-1;
end
end
endmodule
Delays should not be used in the final implementation, so is there another way without using #1?
In essence i want PermutedBitNo = pi_out to be evaluated only after the Pi module has finished its job with pi_in (=8*i+j) as input.
How can i block this line until Pi has finished?
Do i have to use a clock? If that's the case, please give me a hint.
update:
Based on Krouitch suggestions i modified my modules. Here is the updated version:
From pLayer.v:
Pi pi(.clk (clk),
.rst (rst),
.in (pi_in),
.out (pi_out));
counter c_i (clk, rst, stp_i, lmt_i, i);
counter c_j (clk, rst, stp_j, lmt_j, j);
always #(posedge clk)
begin
if (rst) begin
state_out = 0;
end else begin
if (c_j.count == lmt_j) begin
stp_i = 1;
end else begin
stp_i = 0;
end
// here, the logic starts
x = (state_value[(constants.nSBox-1)-i]>>j) & 1'b1;
pi_in = 8*i+j;
PermutedBitNo = pi_out;
y = PermutedBitNo>>3;
tmp[(constants.nSBox-1)-y] ^= x<<(PermutedBitNo-8*y);
// at end
if (i == lmt_i-1)
if (j == lmt_j) begin
state_out = tmp;
end
end
end
endmodule
module counter(
input wire clk,
input wire rst,
input wire stp,
input wire [32:0] lmt,
output reg [32:0] count
);
always#(posedge clk or posedge rst)
if(rst)
count <= 0;
else if (count >= lmt)
count <= 0;
else if (stp)
count <= count + 1;
endmodule
From Pi.v:
always #* begin
if (rst == 1'b1) begin
out_comb = 0;
end
if (in != constants.nBits-1) begin
out_comb = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out_comb = constants.nBits-1;
end
end
always#(posedge clk) begin
if (rst)
out <= 0;
else
out <= out_comb;
end
That's a nice piece of software you have here...
The fact that this language describes hardware is not helping then.
In verilog, what you write will simulate in zero time. it means that your loop on i and j will be completely done in zero time too. That is why you see something when you force the loop to wait for 1 time unit with #1.
So yes, you have to use a clock.
For your system to work you will have to implement counters for i and j as I see things.
A counter synchronous counter with reset can be written like this:
`define SIZE 10
module counter(
input wire clk,
input wire rst_n,
output reg [`SIZE-1:0] count
);
always#(posedge clk or negedge rst_n)
if(~rst_n)
count <= `SIZE'd0;
else
count <= count + `SIZE'd1;
endmodule
You specify that you want to sample pi_out only when pi_in is processed.
In a digital design it means that you want to wait one clock cycle between the moment when you are sending pi_in and the moment when you are reading pi_out.
The best solution, in my opinion, is to make your pi module sequential and then consider pi_out as a register.
To do that I would do the following:
module Pi(in, out);
input clk;
input [31:0] in;
output [31:0] out;
reg [31:0] out;
wire clk;
wire [31:0] out_comb;
always #* begin
if (in != constants.nBits-1) begin
out_comb = (in*constants.nBits/4)%(constants.nBits-1);
end else begin
out_comb = constants.nBits-1;
end
end
always#(posedge clk)
out <= out_comb;
endmodule
Quickly if you use counters for i and j and this last pi module this is what will happen:
at a new clock cycle, i and j will change --> pi_in will change accordingly at the same time(in simulation)
at the next clock cycle out_comb will be stored in out and then you will have the new value of pi_out one clock cycle later than pi_in
EDIT
First of all, when writing (synchronous) processes, I would advise you to deal only with 1 register by process. It will make your code clearer and easier to understand/debug.
Another tip would be to separate combinatorial circuitry from sequential. It will also make you code clearer and understandable.
If I take the example of the counter I wrote previously it would look like :
`define SIZE 10
module counter(
input wire clk,
input wire rst_n,
output reg [`SIZE-1:0] count
);
//Two way to do the combinatorial function
//First one
wire [`SIZE-1:0] count_next;
assign count_next = count + `SIZE'd1;
//Second one
reg [`SIZE-1:0] count_next;
always#*
count_next = count + `SIZE'1d1;
always#(posedge clk or negedge rst_n)
if(~rst_n)
count <= `SIZE'd0;
else
count <= count_next;
endmodule
Here I see why you have one more cycle than expected, it is because you put the combinatorial circuitry that controls your pi module in you synchronous process. It means that the following will happen :
first clk positive edge i and j will be evaluated
next cycle, the pi_in is evaluated
next cycle, pi_out is captured
So it makes sense that it takes 2 cycles.
To correct that you should take out of the synchronous process the 'logic' part. As you stated in your commentaries it is logic, so it should not be in the synchronous process.
Hope it helps

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.

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