Input Output for 8-bit ALU using FPGA board - verilog

I am a newbie to xilinx so please excuse any stupidities in the code.
Ah so I am trying to design an 8-bit ALU and the module is working perfectly on the simulation but we need to take inputs and display outputs on FPGA board.
Technically I should have used RS-232 but since we just have an 8-bit input and 8 switches are available, we are trying to code it this way.
However, the code does not compile and gives error
"expecting 'endmodule', found 'forever'".
I used 'forever' and not 'always' because always does not allow any instance to be instantiated within it.
Can anybody please help us figure out what is wrong with the code?
module main(out,in,switch);
output [7:0] out;
input [7:0] in;
input switch;
reg [7:0] a,b,select;
reg [1:0] count;
wire eq, comp, C8;
initial
begin
count = 2'b00;
select = 8'b0000_0000;
end
MyALU A(eq, comp, C8, out, a, b, 1'b0, select[0], select[1], select[2], select[3]);
forever
begin
if (switch)
begin
case (count)
00:
begin
a = in;
count = 2'b01;
end
01:
begin
b = in;
count = 2'b10;
end
10:
begin
select = in;
A(eq, comp, C8, out, a, b, 1'b0, select[0], select[1], select[2], select[3]);
count = 2'b00;
end
default
a = in;
endcase
end
end

Every module in verilog must end with the line endmodule. That is missing in your code. And try using always#(*) instead of forever. forever is not synthesizable and only used for verification with simulation.

Replace the forever statement by always #(*).
Remove this line from the case statement:
A(eq, comp, C8, out, a, b, 1'b0, select[0], select[1], select[2], select[3]);
Add endmodule at the end.

Related

How to give input to a task

I've created a task in my testbench which takes 3 inputs, but it seems that the value of one of them is wrong.
Below there is my code. I already know that s has the same value of dut.r.f, but when I run the simulation it's not like this.
MAIN:
module main(
input logic clk,
input logic vaux2_p,
input logic vaux2_n,
output logic gpio1,
);
logic [8:0] f;
inst r(
.clk (clk),
.f (f),
);
endmodule
R:
module inst(
input logic clk,
output logic [ 8:0] f
);
always_ff #(posedge clk) begin
f <= 8'h0_F0;
end
endmodule
TESTBENCH:
module m();
logic clk;
logic vaux2_p;
logic vaux2_n;
logic gpio1;
main dut(
.clk(clk),
.vaux12_p (vaux2_p),
.vaux12_n (vaux2_n),
.gpio1 (gpio1)
);
task test;
input [ 7:0] a;
input [8:0] v;
input [8:0] s;
integer f1;
begin
f1 = $fopen("file.txt","w");
if (!f1) begin
$display("File \"file.txt\" cannot be opened!");
end else begin
//this part of code is just for test what I'm reading
$fdisplay(f1," f: %0h %0b %0d", dut.r.f,dut.r.f,dut.r.f);
$fdisplay(f1,"s: %0h %0b %0d", s,s,s);
$fdisplay(f1,"v: %0h %0b %0d", v,v,v);
$fclose(f1);
end
endtask
initial begin
test(8'h19,24'hFF00, dut.r.f);
$finish;
end
endmodule
If I run this code and then I open the file.txt what I can read is this:
f: f0 11110000 240
s: xxxxxx xxxxxxxxxxxxxxxxxxxxxxxx x
v: f0 11110000 240
I was thinking that this can be due to the fact that at the beginning of the simulation dut.r.f=xxxxxx and only after few ns it turns in f0, but then I realized that this cannot be the problem for two reasons: the first one is that if the value of the signals is taken at the beginning of the simulation, also f should be equal to xxxxxx, the second one is that even if I introduce a delay before I display the signal values, the problem still exists.
Do you know if there is any issue in passing a variable from main as input for the task? If yes, it's the same also with functions?
Can anyone kindly help me, please? Thanks!
The problem here is task input arguments get passed by value only when entering the task test. Further updates to the actual arguments to not get passed through. You need to use pass by reference to see later updates.. Change you task declaration to
task test(
input logic [ 7:0] a,
input logic [8:0] v,
ref logic [8:0] s);
int f1;
See this post for more details.
Assuming your provided test bench is complete, the fundamental problem is the clock that dut.r.f is dependent on never toggles.
initial begin
clk = 1'b0; // init clock;
#1; // time to propagate
clk = 1'b1; // will trigger #(posedge clk) if connected properly
#1; // time to propagate
test(8'h19,24'hFF00, dut.r.f);
$finish;
end
If you want to start the task before toggling the clock, you will need to use SystemVerilog's ref instead of input as mentioned in dave_59's answer, and add time delay.

ALU in Verilog: "Unable to bind wire/reg/memory"

I am trying to make a simple 32 bit ALU with an overflow flag, and then output the inputs and results of the ALU to the screen, but I encountered some problems with connecting the elements for the test bench. I got this error:
test_32bALU.v:15: error: Wrong number of ports. Expecting 4, got 5.
test_32bALU.v:33: error: Unable to bind wire/reg/memory
test_unit.overflow' inalu_test'
2 error(s) during elaboration.
I am just starting with Verilog and I have a basic idea of the syntax. I know I am not supposed to ask debugging questions, but this is my only hope. My professor or TA wouldn't respond to me requests for help. I would appreciate it if anyone here could help me point out my mistakes.
This is my 32bALU.v file:
module alu(
input signed[31:0] a,b,
input[3:0] opcode;
output signed[31:0] c;
output overflow;
);
reg signed[31:0] result;
assign c = result;
reg tmp;
parameter
add = 4'b0000,
sub = 4'b0110,
sla = 4'b0001,
srai = 4'b0011;
always #(a,b,opcode)
begin
case(opcode)
add:
begin
c = a + b;
end
endcase
end
always #(c)
begin
if (c[32:31] == (2'b11 | 2'b10)) // Overflow
begin
tmp = 1'b1;
assign overflow = tmp;
end
else begin
tmp = 1'b0;
assign overflow = tmp;
end
end
assign result = c[31:0];
endmodule
test_32bALU.v
`timescale 1ns/1ps
module alu_test;
// Inputs
reg[31:0] a,b;
reg[2:0] opcode;
// Outputs
wire[31:0] c;
//wire [1:0] zero;
wire [1:0] overflow;
//wire [1:0] neg;
alu test_unit(
a,b, // Inputs
opcode,
c,
overflow
);
parameter
add = 4'b0000,
sub = 4'b0110,
sla = 4'b0001,
srai = 4'b0011;
initial begin
$display("op: a : b : c : reg_A : reg_B : reg_C");
$monitor(" %h:%h:%h:%h:%h:%h:%h",
opcode, a, b, c, test_unit.a, test_unit.b, test_unit.c);
$monitor("%h", test_unit.overflow);
//// add
#10 a=32'b0000_0000_0000_0000_0000_0000_0000_0001;
#10 b=32'b0000_0000_0000_0000_0000_0000_0000_0001;
opcode= add;//3'b000
#10 $finish;
end
endmodule
I am confused as to why it says "wrong number of ports"? I assume it's the number of parameters in module alu and alu test_unit? They have the same number of parameters (a, b, c, opcode and overflow), so what exactly am I missing? How exactly do I get the value of overflow? It works fine before I added the overflow parameter, so I assume I'm doing it wrong?
For the second error, I read somewhere on here that it might be due to a missing declaration, but I have declared all of them... so I am not sure what's making it wrong.
I am not sure if this is the issue, but your module definition is not correct. It should be as follows:
module alu(
input signed[31:0] a,b,
input[3:0] opcode,
output signed[31:0] c,
output overflow
);
Perhaps this may help with your issue.
Commas separate inputs and outputs in the module declaration.
NEVER rely on the order of arguments to modules and ALWAYS try to use, for a module called A;
module A(output wire c,
input wire a,
input wire b);
...
endmodule // A
use an instance of it using;
A yourAname(.c(Bar),
.a(Foo1),
.b(Foo2));
so that if the definition and order of the I/O of the module changes, this instantiation will track those changes and/or give appropriate errors when simulated/synethesised.
You might find it useful to follow a few simple rules in your source code when naming;
inputs are denoted by i_yourinputname
outputs are denoted by o_youroutputname
inout are denoted by io_yourinputoutputname
wire are denoted by w_yourwirename
reg are denoted by r_yourregname
as this avoid confusion and is a good habit to get into as soon as possible when starting to learn verilog.

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.

How to get MAX or MIN in Verilog?

I want to build a simple module to compare two 2-bit numbers and get the maximum number in the output.
I've used the code posted here: How to find MAX or MIN in Verilog coding?
module max (input [1:0] a,
input [1:0] b,
output reg [1:0] out);
always #* begin
if (a>b)
out = a;
else
out = b;
end
endmodule
But the problem I have, is that the output "out" does not give me a 2-bit number, and also the code is not working well as you can see in the screenshot.
This is the testbench I'm using:
`timescale 1ns/10ps
module maxTB();
reg [1:0] a, b;
max dut (.a(a),.b(b),.out(out));
initial
begin
a = 2'b1; b= 2'b0;
#20 a = 2'b10;
#40 b = 2'b11;
#50 a = 2'b01;
end
endmodule
modelsim screenshot
You haven't declared out in your TB, so it has defaulted to a 1-bit net (a wire). This is a rather major failing in the language. To turn this behaviour off, add this outside any module:
`default_nettype none

Shifting a Concatenate Register

Ive been doing verilog HDL in quartus II for 2 month now and have not synthesized any of my codes yet. I am struggling to code a fractional division circuit. Of course theres a lot of problems...
I would like to know how do I concatenate two registers to form a larger register that I can shift to the right where the shifting of the data would occur at every positive edge of the clock pulse... The data in the newly created register has 3 zeros (MSB) followed by 4 data bits from another register called divider.
For example B=[0 0 0]:[1 0 1 0]
I have tried the following
module FRACDIV (divider,clk,B,START,CLR);
input [3:0] divider;
input START, CLR, clk;
output [6:0] B;
reg [6:0] B;
always # (posedge clk)
begin
B = {3'd0, divider};
if (START == 1'b1)
begin
B=B+B<<1;
end
end
endmodule
Any help would be deeply appreciated as I've been trying to figure this out for 5 hours now...
Mr. Morgan,
Thank you for the tips. The non-blocking statement did help. However the code would not shift perhaps because B is always reinitialized at every clock pulse as it is outside the if statement.
With a fresh new day and a fresh mind and owing to your suggestion using the non-blocking statement I tried this...
module FRACDIV(divider,clk,B,START,CLR);
input [3:0] divider;
input START, CLR, clk;
output [6:0] B;
reg [6:0] B;
always # (posedge clk)
begin
if (START) begin
B <= {3'b0, divider};
end
else begin
B <= B <<1;
end
end
endmodule
The if statement loads data into B whenever START is HIGH. When START is LOW, the data shifts at every positive edge of the clock. Is there anyway to make the data in B to start shifting right after loading it with the concatenated data without the if statement?
Just curious and I still do not feel this code is the most efficient.
When implying flip-flops it is recommended to use <= non-blocking assignments.
When declaring outputs you should also be able to delcare it as a reg, unless you are stuck using a strict verilog-95 syntax.
module FRACDIV (
input [3:0] divider,
input START, CLR, clk,
output reg [6:0] B
);
always # (posedge clk) begin
B <= {3'd0, divider};
if (START == 1'b1) begin
B<=B+B<<1; //This will overide the previous statement when using `<=`
end
end
endmodule
This will simulate in the same way that your synthesised code will perform on the FPGA.

Resources