I have written all the code, including the modules, but I can't figure out how to wire the modules to the main program.
The ALU should be:
A (4bits) and B (4bits) as inputs, sel (3bits)
1st Module When sel = 000 => Add/ sel= 001 => Sub (A+B or A-B)
2nd Module When sel = 010 => Shift right by 1
3rd Module when sel = 011 => Multiply (A*B)
4th Module When sel = 100 => A XNOR B
5th Module When sel = 101 => Compare A==B
I also made a 6th module with a Mux6to1.
It has to be on a gate level. Can't use (+/-). This is the code I've been writing but when I simulate, I just get the result: ZZZZZZZZ. Please, any suggestions would be appreciated, thanks.
For Add/Sub 1 bit:
module Full_Adder_1bit(a,b,cin,sel,sum,cout);
input a, b, cin;
input [2:0] sel;
output sum, cout;
reg sum, cout;
reg a_in;
always # (a or b or cin or sel)
begin
a_in = a^sel[0];
sum = a^b^cin;
cout = (a_in&b)|(a_in&cin)|(b&cin);
end
endmodule
For 4 bit ADD/SUB:
module Full_Adder_4bits (a, b, cin, sel, sum, cout);
input [3:0] a, b;
input [2:0] sel;
input cin;
output [3:0] sum;
output cout;
wire c1,c2,c3;
Full_Adder_1bit FA0(a[0],b[0],cin,sel,sum[0],c1);
Full_Adder_1bit FA1(a[1],b[1],c1,sel,sum[1],c2);
Full_Adder_1bit FA2(a[2],b[2],c2,sel,sum[2],c3);
Full_Adder_1bit FA3(a[3],b[3],c3,sel,sum[3],cout);
endmodule
For the Shifter:
module Shifter(dataIn, shiftOut);
output [3:0] shiftOut;
input [3:0] dataIn;
assign shiftOut = dataIn >> 1;
endmodule
For the XNOR:
module XNOR(a,b,rxnor);
input [3:0] a,b;
output [3:0] rxnor;
reg rxnor;
always # (a or b)
begin
rxnor= a~^b; //XNOR
end
endmodule
For Multiplier:
module mul4 (i0,i1,prod);
input [3:0] i0, i1;
output [7:0] prod;
assign prod = i0*i1;
endmodule
For Compare:
module Compare(B,A,R);
input [3:0] A,B;
output [3:0] R;
reg R;
always#(A,B)
begin
if (A==B)
R = 4'b0001;
else if (A==B)
R = 4'b0000;
else
R = 4'b1111;
end
endmodule
For the mux (it is actually 5 to 1 even though the name says 6 to 2):
module MUX6to2(i0,i1,i2,i3,i4,sel,out);
input [4:0] i0,i1,i2,i4;
input [7:0] i3;
input [2:0] sel;
output [7:0] out;
reg [7:0] out;
always # (i0 or i1 or i2 or i3 or i4 or sel)
begin
case (sel)
3'b000: out = i0;
3'b001: out = i0;
3'b010: out = i1;
3'b011: out = i2;
3'b100: out = i3;
3'b100: out = i4;
default: out = 8'bx;
endcase
end
endmodule
For the ALU:
module ALU(a,b,cin,sel,r,cout);
input [3:0] a, b;
input [2:0] sel;
input cin;
output [7:0] r;
output cout;
wire [3:0] add_out, shift_out, xnor_out, compare_out;
wire [7:0] mul_out;
wire cout;
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
Full_Adder_4bits output_adder (a,b,cin,sel [2:0],add_out,cout);
Shifter output_shifter (a,shift_out);
XNOR output_XNOR (a,b,xnor_out);
mul4 output_mul4 (a,b,mul_out);
Compare output_Compare (a,b,compare_out);
endmodule
Why the value of output "r" Hi-Z is you haven't connected anything to output so the default value of wire is propagated in the output
When it comes to your design a decoder is required and for arithmetic operation operand size has to be taken care
Required bit widths are
addition 4 bit + 4 bit = 4 bit + carry,
subtraction 4 bit - 4 bit = 4 bit + borrow,
shifting which of them should be shifted and required bit width needs to be calculated,
multiplication 4*4 bit = 8 bit is needed,
xnor 4 bit xnot 4 bit = 4 bit needed,
compare it is up how we represent if equal with 1 bit or any bit widths
In your Mux logic you have
3'b100: out = i3;
3'b100: out = i4;
Here in this both case items are same so synthesizer optimizes and only considers the first statement and ignores the second, in general case should not be coded this way and more over this mux itself is not necessary.
Coming to your top module ALU, the syntax is wrong, this type of assignments are not permitted in verilog HDL
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
When integrating all modules you have to be clear about what you are going to connect and widths with hardware in mind map,
Considering your design
The adder will result in 4bit + carry but output "r" is 8 bit so other bits should made to constant value or else it will be defaulted to X in case reg or Hi-z in case wire in the output, similar for other operations too.
I have made some modification in the design with a decoder and found to be fully functional,
A (4bits) and B (4bits) as inputs, sel (3bits)
When sel = 000 => Add/ sel= 001 => Sub (A+B or A-B)
When sel = 010 => Shift right by 1
when sel = 011 => Multiply (A*B)
When sel = 100 => A XNOR B
When sel = 101 => Compare A==B
Give a try of the code http://www.edaplayground.com/x/DaF
in the module ALU, check the port list which where mapped to multiplexer module as emman said.
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
in this module, the output which declared is of size 8 bit r. but, in some cases add_out, shift_out, xnor_out, compare_outthe size is 4 bits only. so, during the case of these outputs, the output 'r' shows 4 X's.
module ALU(a,b,cin,sel,r,cout);
input [3:0] a, b;
input [2:0] sel;
input cin;
output [7:0] r;
output cout;
wire [3:0] add_out, shift_out, xnor_out, compare_out;
wire [7:0] mul_out;
wire cout;
// MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
MUX6to2 output_mux (add_out, shift_out, xnor_out, mul_out, compare_out, sel[2:0], r);
Full_Adder_4bits output_adder (a,b,cin,sel [2:0],add_out,cout);
Shifter output_shifter (a,shift_out);
XNOR output_XNOR (a,b,xnor_out);
mul4 output_mul4 (a,b,mul_out);
Compare output_Compare (a,b,compare_out);
endmodule
Does your code compile properly? I can see a problem in this line:
MUX6to2 output_mux (Full_Adder_4bits, Shifter, XNOR, mul4, Compare, sel[2:0], r);
Full_Adder_4bits, Shifter, etc. are names of your modules, not a valid signal names. What you meant is probably this:
Mux6to2 output_mux (adder_out, shifter_out, xnor_out, mul_out, compare_out, sel, r);
Related
I have a problem in PISO verilog register.
Below is my code
`timescale 1ns / 1ps
module PISO(
input clk,
input load,
input [3:0] d,
output reg Qout);
reg [3 : 0]Q;
always # (posedge clk)
begin
if ( load )
Q <= d;
else
begin
Qout <= d[3];
Q<= { Q[2:0] , 1'b0 };
end
end
endmodule
and my testbench
`timescale 1ns / 1ps
module PISO_tb();
PISO uut(clk,load,d,Qout);
reg clk;
reg load;
reg [3:0]d;
wire Qout;
initial begin
clk=0;
forever #5 clk = ~clk;
end
initial begin
load = 1;
d[0] = 1'b0;
d[1] = 1'b1;
d[2] = 1'b0;
d[3] = 1'b1;
#6 load = 0;
end
endmodule
And it isn't working as it should, please help me with testbench maybe? Because I think the verilog code is okay and it should work properly.
You want the Qout signal to be the output of the shift register (Q) instead of the input, so that the output toggles instead of remaining at 1. Change:
Qout <= d[3];
to:
Qout <= Q[3];
I am having a small issue here in when I instantiated my modules. I am using a generate loop to create 100 instances of 2 counters (16 & 32 bit counters). Each counter should have their own independent controls (UPDN & EN), but they share a clock and a reset.
Module Descriptions:
SAT_COUNTER.sv // SIMPLE COUNTER MODULE
TWO_SC.sv // INSTANTIATES TWO SAT_COUNTER MODULES (16 BIT & 32 BIT
COUNTERS)
GEN_SC.sv // INSTANTIATES 100 MODULES OF TWO_SC MODULES
tb_GEN_SC.sv // TESTBENCH
I am sure that my problem is in the GEN_SC module where I instantiate all 100..
I appreciate any help! Thank you in advance!
module SAT_COUNTER(
COUNT, // SCALABLE COUNT OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE LOW RESET
UPDN, // COUNTER WILL COUNT: UP = 1; DN = 0;
EN); // ENABLE
parameter WIDTH = 8;
input CLK, al_RST, UPDN, EN;
output reg [WIDTH-1:0] COUNT;
...
endmodule
//**********************
module TWO_SC(
COUNT1, // N-BIT COUNTER OUTPUT
COUNT2, // M-BIT COUNTER OUTPUT
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN, EN;
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
SAT_COUNTER #(WIDTH1) GSC1(.COUNT(COUNT1), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[0]), .EN(EN[0]));
SAT_COUNTER #(WIDTH2) GSC2(.COUNT(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[1]), .EN(EN[1]));
endmodule
//**********************
module GEN_SC(
COUNT1, // COUNT1
COUNT2, // COUNT2
CLK, // CLOCK
al_RST, // ACTIVE-LOW RESET
UPDN, // DIR. CONTROL
EN); // ENABLE
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
input CLK, al_RST;
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
output [WIDTH1-1:0] COUNT1;
output [WIDTH2-1:0] COUNT2;
genvar j;
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1), .COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
endmodule
//**********************
module tb_GEN_SC();
parameter MOD_COUNT = 100;
parameter WIDTH1 = 16;
parameter WIDTH2 = 32;
reg CLK, al_RST;
reg [1:0] UPDN [MOD_COUNT-1:0];
reg [1:0] EN [MOD_COUNT-1:0];
wire [WIDTH1-1:0] COUNT1;
wire [WIDTH2-1:0] COUNT2;
GEN_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) UUT(COUNT1, COUNT2, CLK, al_RST, UPDN, EN);
initial begin
CLK = 1'b1;
forever
#5 CLK = ~CLK;
end
initial
$monitorb("%d COUNT = %b (%d) | UPDN = %b | EN = %b | COUNT = %b (%d) | UPDN = %b | EN = %b | al_RST = %b | CLK = %b", $time, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.COUNT1, UUT.SC[87].TWOCOUNTERS.UPDN[0], UUT.SC[87].TWOCOUNTERS.EN[0], UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.COUNT1, UUT.SC[99].TWOCOUNTERS.UPDN[0], UUT.SC[99].TWOCOUNTERS.EN[0], al_RST, CLK);
initial begin
$vcdpluson;
UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 0; al_RST = 1;
#10 UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 0; al_RST = 0; // RESET COUNTER
#10 EN = 1; al_RST = 1; // ENABLE COUNTER AND COUNT UP (HITS MAX)
#200 UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 0; UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1; EN = 1; // BEGIN TO COUNT DOWN
#10 EN = 0;
#60 EN = 3;
// #230 UPDN = 1; UPDN = 0;
#3017 al_RST = 0;
#100 al_RST = 1;
#20 $finish;
end
/////////// ERRORS I GET /////////////////
Error-[IBLHS-NT] Illegal behavioral left hand side
tb_GEN_SC.sv, 34
Net type cannot be used on the left side of this assignment.
The offending expression is : tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN
Source info: tb_GEN_SC.UUT.SC[87].TWOCOUNTERS.GSC1.UPDN = 1;
Error-[IBLHS-NT] Illegal behavioral left hand side
tb_GEN_SC.sv, 34
Net type cannot be used on the left side of this assignment.
The offending expression is : tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN
Source info: tb_GEN_SC.UUT.SC[99].TWOCOUNTERS.GSC1.UPDN = 1;
Error-[IUDA] Incompatible dimensions
tb_GEN_SC.sv, 34
Incompatible unpacked dimensions in assignment
Arrays with incompatible unpacked dimensions cannot be used in assignments,
initializations and instantiations.
Error-[ICTA] Incompatible complex type
tb_GEN_SC.sv, 34
Incompatible complex type assignment
Type of source expression is incompatible with type of target expression.
Mismatching types cannot be used in assignments, initializations and
instantiations. The type of the target is 'reg[1:0]$[99:0]', while the type
of the source is 'int'.
Source Expression: 0
You have just one UPDB and one EN port in port list. So how you wana apply different UPDN and EN to instances?
An idea is to define an array with size of MOD_COUNT so that each element has its own control input. then in genvar loop you can use the index. like this:
input [1:0] UPDN [MOD_COUNT-1:0];
input [1:0] EN [MOD_COUNT-1:0];
...
generate
for(j = 0; j < MOD_COUNT; j++) begin: SC
TWO_SC #(.WIDTH1(WIDTH1), .WIDTH2(WIDTH2)) TWOCOUNTERS(.COUNT1(COUNT1),
.COUNT2(COUNT2), .CLK(CLK), .al_RST(al_RST), .UPDN(UPDN[j]), .EN(EN[j]));
end
endgenerate
I am trying to figure out how to use the block RAM on my iCE40HX-8K Breakout Board. I would like to access it in a 512x8 configuration, which as far as I can tell from the documentation is supported by project IceStorm, but I haven't been able to get it to work like I expected.
If I understand correctly, initializing an SB_RAM40_4K primitive with the READ_MODE parameter set to 1 should set the block up in 512x8 read mode, which uses a 9 bit read address, and reads 8 bits of data at each address.
Here is the simplest example I could think of. It sets up an SB_RAM40_4K with some pre-initialized memory and reads straight to the pins of the on-board LED's.
hx8kboard.pcf
set_io leds[0] B5
set_io leds[1] B4
set_io leds[2] A2
set_io leds[3] A1
set_io leds[4] C5
set_io leds[5] C4
set_io leds[6] B3
set_io leds[7] C3
set_io clk J3
top.v
module top (
output [7:0] leds,
input clk
);
//reg [8:0] raddr = 8'd0;
reg [8:0] raddr = 8'd1;
SB_RAM40_4K #(
.INIT_0(256'h00000000000000000000000000000000000000000000000000000000_44_33_22_11),
.WRITE_MODE(1),
.READ_MODE(1)
) ram40_4k_512x8 (
.RDATA(leds),
.RADDR(raddr),
.RCLK(clk),
.RCLKE(1'b1),
.RE(1'b1),
.WADDR(8'b0),
.WCLK(1'b0),
.WCLKE(1'b0),
.WDATA(8'b0),
.WE(1'b0)
);
endmodule
LED output when raddr == 0
\|/ \|/
O O O O O O O O
LED output when raddr == 1
\|/ \|/ \|/ \|/
O O O O O O O O
I would think that address 1 in 512x8 mode would be the second 8 bits from RAM, which is 8'h22 or 8'b0010010. Instead I get 8'h33 or 8'b00110011. After a little experimentation, this seems to be the lower 8 bits of a 16 bit read.
I'm not sure where I went wrong. Any help understanding what's going on here would be appreciated. Thanks!
This question is not really about Yosys or Project IceStorm. The format used for the SB_RAM40_4K INIT_* parameters is the same for the IceStorm flow and the Lattice iCEcube2 flow. However, Lattice has done a very very bad job at documenting this format. Otherwise I'd just point you to the right Lattice document.. :)
You are interested in the 512x8 mode. First you need to know that in 512x8 mode only the even bits of .RDATA() and .WDATA() are used (not the 8 LSB bits, as your code suggests!).
The data in .INIT_* is stored as 16 16-bit words per parameter. The lowest 16-bit word in .INIT_0() contains the 8-bit word at addr 0 in its even bits and the 8-bit word at addr 256 in its odd bits.
The next 16-bit word in .INIT_0() contains words 1 and 257. The lowest 16-bits in .INIT_1() contain words 16 and 272, and so forth.
The easiest way to investigate this kind of stuff is probably to either read the SB_RAM40_4K simulation model in /usr/local/share/yosys/ice40/cells_sim.v, or simply let Yosys infer the memory and observe what yosys does. For example the following design:
module test(input clk, wen, input [8:0] addr, input [7:0] wdata, output reg [7:0] rdata);
reg [7:0] mem [0:511];
initial mem[0] = 255;
always #(posedge clk) begin
if (wen) mem[addr] <= wdata;
rdata <= mem[addr];
end
endmodule
Will produce the following output when run through yosys -p 'synth_ice40; write_verilog' test.v:
(* top = 1 *)
(* src = "test.v:1" *)
module test(clk, wen, addr, wdata, rdata);
(* src = "/usr/local/bin/../share/yosys/ice40/brams_map.v:255" *)
(* unused_bits = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" *)
wire [15:0] _0_;
(* src = "test.v:1" *)
input [8:0] addr;
(* src = "test.v:1" *)
input clk;
(* src = "test.v:1" *)
output [7:0] rdata;
(* src = "test.v:1" *)
input [7:0] wdata;
(* src = "test.v:1" *)
input wen;
(* src = "/usr/local/bin/../share/yosys/ice40/brams_map.v:277|/usr/local/bin/../share/yosys/ice40/brams_map.v:35" *)
SB_RAM40_4K #(
.INIT_0(256'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x1x1x1x1x1x1x1),
.INIT_1(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_2(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_3(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_4(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_5(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_6(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_7(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_8(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_9(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_A(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_B(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_C(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_D(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_E(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.INIT_F(256'hxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx),
.READ_MODE(32'sd1),
.WRITE_MODE(32'sd1)
) \mem.0.0.0 (
.MASK(16'hxxxx),
.RADDR({ 2'h0, addr }),
.RCLK(clk),
.RCLKE(1'h1),
.RDATA({ _0_[15], rdata[7], _0_[13], rdata[6], _0_[11], rdata[5], _0_[9], rdata[4], _0_[7], rdata[3], _0_[5], rdata[2], _0_[3], rdata[1], _0_[1], rdata[0] }),
.RE(1'h1),
.WADDR({ 2'h0, addr }),
.WCLK(clk),
.WCLKE(wen),
.WDATA({ 1'hx, wdata[7], 1'hx, wdata[6], 1'hx, wdata[5], 1'hx, wdata[4], 1'hx, wdata[3], 1'hx, wdata[2], 1'hx, wdata[1], 1'hx, wdata[0] }),
.WE(1'h1)
);
endmodule
(Scroll all the way to the right to see the initialization pattern generated for the mem[0] = 255 initialization.)
I am just beginning to learn verilog. I wrote two programs for that purpose. Here is my first program:
module test1(i,o);
input i;
output o;
wire[0:63] i;
wire[0:63] o;
assign o = i * 2.0;
endmodule
module test1_tb();
reg[0:63] inp;
wire[0:63] outp;
initial
begin
assign inp = 2.0;
$monitor("input=%f, output=%f",inp,outp);
end
test1 t1(inp,outp);
endmodule
This gives me the following result when I run it in ModelSim:
# input=2.000000, output=4.000000
Then I edited the above program as follows:
module test1(i1,i2,h1,w1,w2,b1);
input i1;
input i2;
input w1;
input w2;
input b1;
output h1;
wire[0:63] i1;
wire[0:63] i2;
wire[0:63] h1;
wire[0:63] w1;
wire[0:63] w2;
wire[0:63] b1;
assign h1 = 1/(1+ 2.718281828459**((-1.0)*(i1 * w1 + i2 * w2 + b1)));
endmodule
module test1_tb();
reg[0:63] i1;
reg[0:63] i2;
reg[0:63] w1;
reg[0:63] w2;
reg[0:63] b1;
wire[0:63] h1;
initial
begin
assign i1 = 0.05;
assign i2 = 0.10;
assign w1 = 0.15;
assign w2 = 0.20;
assign b1 = 0.35;
$monitor("i1=%f, i2=%f, w1=%f, w2=%f, b1=%f, h1=%f",i1,i2,w1,w2,b1,h1);
end
test1 n1(i1,i2,h1,w1,w2,b1);
endmodule
For this program I get the output:
# i1=0.000000, i2=0.000000, w1=0.000000, w2=0.000000, b1=0.000000, h1=1.000000
It seems the module does not get the initial values in the second program. But all I did was adding few more input lines to the first program and changing the calculation.
Right now I don't know what's the error with this. Please help.
The type reg is not designed to implicitly handle floating point math. As such, real constants assigned to the reg variables are rounded to the nearest integer (see IEEE1800-2012 Section 5.7.2, SystemVerilog LRM; sorry I dont have IEEE1364, Verilog LRM, to find the reference in there).
If you simply want to do some floating point math, you can use the real type which is the same as a double. Otherwise, if you want to do floating point math in hardware, youll need to deal with the complexities of it yourself (or borrow from an IP core). Also note that Verilog is not a scripting language, but a Hardware Descriptive Language, so unless you are trying to design hardware, you are much better off using Python, Ruby or Perl for general purpose stuff.
I'm trying to write the test bench for my ALU but. I'm not sure if its written in a way that makes it work. For instance, should I use dut or uut? Have I initialized my inputs correctly? The output wave is just straight (doesn't change with each bit X's and one 0).
module Alu_test();
reg [7:0]pc;
reg [3:0] CCRin;
reg rst,clk;
reg [3:0] opcode;
reg[7:0] ra;
reg[7:0] rb;
reg [7:0] in_port;
reg[7:0] SP; //= 255
wire[7:0] SP_out;
wire [7:0] out_port;
wire[255:0] dmem;
wire[7:0] ra_out;
wire[7:0] rb_out;
wire [3:0] CCRo;
wire [7:0] npc;
ALU dut(opcode,ra,rb,ra_out,rb_out,rst,clk,pc,npc,CCRin,CCRo,SP,SP_out,in_port,out_port,dmem);
initial
begin
rst = 0;
clk = 0;
opcode = 0;
SP = 255;
CCRin = 0;
pc = 0;
in_port = 0;
ra = 0;
rb = 0;
#5
forever
#5 clk = ~clk;
#50
#5 opcode[3:0] = 4'b0000; //nop
#5 opcode[3:0] = 4'b0100; //add
ra =1;
rb =1;
#5 opcode[3:0] = 4'b0111; //shift left
ra =1;
rb =0;
#5 opcode[3:0] = 4'b1010; //push
ra =1;
rb =2;
end
endmodule
this is the module
module ALU(opcode,ra,rb,ra_out,rb_out,rst,clk,pc,npc,CCRin,CCRo,SP,SP_out,in_port,out_port,dmem);
wire [7:0] res; // result
input wire [7:0]pc;
output reg [7:0] npc;
input rst,clk;
input wire [3:0] opcode;
input wire[7:0] ra;
input wire[7:0] rb;
output reg[7:0] ra_out;
output reg[7:0] rb_out;
input wire[7:0] SP; // testbench haygebli SP el mafroud yeb2a = 255
output reg[7:0] SP_out;
input wire [7:0] in_port;
output reg [7:0] out_port;
output reg[255:0] dmem;
input wire [3:0] CCRin;
output reg [3:0] CCRo;
wire co;
wire cin;
wire [7:0] result; //total result
always #(posedge clk)
begin
SP_out = SP;
end
assign result = alu_out(ra,rb,cin);
assign res = result[1:0];
assign co = result[2];
function [8:0] alu_out;
input [1:0] ra,rb;
input cin;
case (opcode)
0: ;
4: assign alu_out = ra + rb;
5: assign alu_out = ra - rb;
6: assign alu_out = ~(ra & rb);
7: assign alu_out = {ra[7:0],cin};
8: assign alu_out = {ra[0],cin,ra[7:1]};
10: if (ra == 1)
begin
dmem[SP_out] = rb;
SP_out = SP_out-1;
end
else
begin
SP_out = SP_out +1;
rb_out = dmem[SP_out];
end
11: assign out_port = ra;
12: assign ra_out = in_port;
13: assign ra_out = rb;
default: begin
alu_out = 8'bxxxxxxxx;
end
endcase
endfunction
always#(posedge clk)
begin
if (res == 0)
CCRo[0] = 1;
else if ( res < 0)
CCRo[1] = 1;
else if (co == 1)
CCRo[2] = 1;
else if ( res < 0 & res > result)
CCRo[3] = 1;
else
CCRo = CCRin;
if (res)
ra_out = res;
npc = pc+1;
end
endmodule
Using dut as the instance name is fine. You can also use uut instead, if you prefer.
You should move the clock generation into its own initial block, then call $finish at the end of your original initial block. This should get you further. Now, 4 signals become known:
initial begin
rst = 0;
opcode = 0;
SP = 255;
CCRin = 0;
pc = 0;
in_port = 0;
ra = 0;
rb = 0;
#5;
#50;
#5 opcode[3:0] = 4'b0000; //nop
#5 opcode[3:0] = 4'b0100; //add
ra =1;
rb =1;
#5 opcode[3:0] = 4'b0111; //shift left
ra =1;
rb =0;
#5 opcode[3:0] = 4'b1010; //push
ra =1;
rb =2;
$finish;
end
initial begin
clk = 0;
forever #5 clk = ~clk;
end
Your dmem initializes to X. You need to drive in opcode=10 to set it to another value.