I2S Transmitter Verilog Implementation not working - verilog

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.

Related

How to properly pass data to a submodule and get results back in verilog?

Say I have a submodule and want to "call" it from a top module.
//sub.v
module sub(
input wire clk,
input wire rst_n,
input wire update,//interface is modifiable
input wire [7:0] in_data,
output wire[7:0] out_data
);
reg[7:0] state;
always #(posedge clk) begin
if(!rst_n)
state<=0;
else if(update)
state<=state+in_data;//update drives states to change according to input data
end
assign out_data=state<<1;
endmodule
//top.v
module top(
input wire clk,
input wire rst_n,
output reg[7:0] top_out
);
//Submodule
reg sub_update;
reg[7:0] sub_in;
wire[7:0] sub_out;
sub sub_instance(
.clk(clk),
.rst_n(rst_n),
.update(sub_update),
.in_data(sub_in),
.out_data(sub_out)
);
//Topmodule
reg[7:0] top_state;
localparam STATE0 = 8'd0;
localparam STATE1 = 8'd1;
localparam STATE2 = 8'd2;
localparam STATE3 = 8'd3;
localparam TEMP_STATE = -8'd1;
always #(posedge clk) begin
if(!rst_n) begin
top_state <= STATE0;
sub_update <= 0;
sub_in <= 0;
end else begin
case (top_state)
STATE0:top_state<=STATE1;
STATE1:begin
//want to update the submodule and use its output here
sub_in <= 123;
sub_update <= 1;
top_state <= TEMP_STATE;
end
STATE2:top_state<=STATE3;//proceed from STATE1
TEMP_STATE:begin
sub_update <= 0;
top_out <= sub_out+1;
top_state <= STATE2;
end
default:top_state<=STATE0;
endcase
end
end
endmodule
The main question may divide into 2 smaller questions:
In my module code, the "update" signal is both set and captured at the same edge of a same clock. Is that a data race? Should I use a different edge, or pass a reverse clock to the submodule? Or should I change "update" to other interface?
Is there a better way to get the submodule output than using a temporary state? For this simple example, there is a way to calculate the output when the input is ready: Inline everything, get top_out<=((state+123)<<1)+1; at STATE1. Can this be generalized for more complicated calculation?
there is no problem in setting and capturing 'update' on the same clock edge. Just note that it will be captured with a delay of one clock cycle after it is set. This is the way flops work and your simulation should work same way because you did correctly use NBAs.
This is the question that you should answer for yourself. Better ways or not depend on your requirements and abilities of hardware. You have all these parts of the equation and states for some reason. You can probably collapse them if your algorithm allows it. You can use complex calculations there if they do not violate your design rules.

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;

assimilating values to registers in GCD FSM in verilog

I'm trying to create a state machine for the GCD algorithm(subtraction method), and I need to put the values(wires) of my numbers to a register to work with the algorithm, but I don't want for each value change to assimilate into the registers.
in other words:
module GCD_R (u,v,out,nrst,act,clk);
input [31:0] A,B;
input clk,act,rst;
output reg [31:0] out;
reg[4:0] state,next_state;
reg[31:0] A_reg,B_reg,Aint_reg,Bint_reg;
parameter IDLE = 4'b0001;
parameter ABIG = 4'b0010;
parameter BBIG = 4'b0100;
always #(A,B)
begin
A_reg<=A
B_reg<=B
end
always #*
case (state)
IDLE: begin
but this definition is problematic since if someone changes the values of A or B, it will move them to the registers every time and I don't want that, basically I need some condition that will move the values to the registers only on initialization, how do I do that?
Usually for such issues clocks are used. You even have it in parameters. So, use it:
always #(posedge clk) begin
A_reg<=A
B_reg<=B
end
Usually for such designs, Clock Edges along with the reset signal is used.
always # (posedge clk, negedge rst)
begin
if (!rst)
begin
// For initialisation
A_reg<=A
B_reg<=B
end
else
begin
// For non initialisation operation to retail value
A_reg<=A_reg;
B_reg<=B_reg;
end
end

Module not properly instantiated?

I have an example code about T-Bird Tail Lights, and it's passing states to the next module. I modified the code that it doesn't have to pass the state, but it seems the output is not changing(stays 000 all the time)
Here's my modified code:
module TBird(E,B,L,R,int_clk,L_Light,R_Light);
input E,B,L,R,int_clk;
output [2:0] L_Light;
output [0:2] R_Light;
reg [19:0] C;
wire int_clk;
One_Side U1 (E,B,R,int_clk,R_Light);
One_Side U2 (E,B,L,int_clk,L_Light);
endmodule
module One_Side(e,b,t,clk,light_eb);
input e,b,t,clk;
output reg [2:0] light_eb=3'b000;
always #(posedge clk or e or b or t)
begin
case ({e,b,t})
3'b000: light_eb=3'b000;
3'b0?1: begin
if (light_eb==3'b000) begin
light_eb=3'b001;
end else if (light_eb==3'b001) begin
light_eb=3'b011;
end else if(light_eb==3'b011) begin
light_eb=3'b111;
end else begin
light_eb=3'b000;
end
end
3'b?10: light_eb=3'b111;
3'b10?: begin
if (light_eb!==(3'b000|3'b111)) begin
light_eb=3'b000;
end
light_eb=~light_eb;
end
3'b111: begin
if (light_eb==3'b000) begin
light_eb=3'b001;
end else if (light_eb==3'b001) begin
light_eb=3'b011;
end else if(light_eb==3'b011) begin
light_eb=3'b111;
end else begin
light_eb=3'b000;
end
end
endcase
end
endmodule
I have had some experience in Java, but I don't know much about verilog, so I don't even know where goes wrong(in Java, eclipse has break points and debugger and things like that,) any suggestions/recommendations are appreciated.
A couple of mistakes in the testbench and design. Listed down as follows:
You have not provided any toggling on clock signal. So there will not be any posedge of clock detected. There are many ways for generating clock, one of them is as follows:
always #5 clk = ~clk;
Using a reset signal in design is good practice. Apply reset from testbench to set all the internal registers in design to their initial values.
The most important thing is you have not provided any input stimulus to the design. Any random stimulus must be applied to get the output. You have to provide some inputs to get the output, henceforth your output is x.
initial
begin
forever
begin
#6;
E = $random;
B = $random;
R = $random; // and so on...
end
end
Use of nonblocking (<=) assignments in design is a good coding practice. Also, donot mix blocking (=) and nonblocking (<=) assignments.
a = b; // never use this in sequential circuit.
a<= b; // use this in sequential circuit.
I have made a somewhat valid testbench for your design, have a look at EDAPlayground link.
Must refer to this, this, and this links for understanding general testbench architecture.

8-bit Adder Error: The logic does not match a known FF or Latch template

As far as I can understand that the hardware required to implement the code below is not supported in Xilinx ISE Web Pack. I'm trying to implement only the functionality of the 8-bit adder using an always block. Here's the code:
module Addr_8bit(Clk, Rst, En, LEDOut
);
input Clk;
input Rst;
input En;
output reg [7:0] LEDOut;
always #(posedge Clk or posedge Rst) begin
if(Rst)
LEDOut <= 8'b00000000;
if(En)
LEDOut <= LEDOut + 8'b00000001;
end
endmodule
The error is on the line where the non-blocking assignment: LEDOut <= LEDOut + 8'b00000001; is located.
Particularly it says that:
ERROR:Xst:899 - "Addr_8bit.v" line 33: The logic for <LEDOut> does not match a known FF or Latch template. The description style you are using to describe a register or latch is not supported in the current software release.
I am trying to make the LEDOut's 8-bit output to correspond to the each single one of 8 LEDs on the BASYS2 FPGA Board(Spartan-3E).
Thank You.
Change your behavioral description (the code inside the always block) as follows:
always#(posedge CLK or negedge RST) begin
if(!RST) begin // Reset condition goes here
LEDOut <= 0;
end
else begin // Everything else goes here
if(En)
LEDOut <= LEDOut + 1'b1;
end
end
The reason your code won't synthesize is because you generally can't assign to the same register under the same edge of two different signals. (You can't have your always block trigger on the low to high transition of CLK and RST if you're assigning to a variable in both cases.) So you can't trigger the reset condition on the positive edge of RST, but you can do it on the negative edge. This is due to the way the physical register elements (called flip-flops) are designed.

Resources