How to add 3 number together? - chisel

There are 3 Uint 8 bits numbers. I want to sum up these numbers. How to describe it in chisel?
s = a + b + c // s is 10 bits number
If the only way to describe it as following, what's the benefits compare to traditional HDL?
s0 = a + b // s0 is 9 bits numebr
s1 = s0 + c // s1 is 10 bits number
I already try it in chisel, the result is not what I expect.
val in0 = Input(UInt(8.W))
val in1 = Input(UInt(8.W))
val p_out = Output(UInt(10.W))
io.p_out := io.in0 + io.in0 - io.in1
The generated RTL:
input [7:0] io_in0,
input [7:0] io_in1,
output [9:0] io_p_out
wire [8:0] _T_18;
wire [7:0] _T_19;
wire [8:0] _T_20;
wire [8:0] _T_21;
wire [7:0] _T_22;
assign io_p_out = {{2'd0}, _T_22};
assign _T_18 = io_in0 + io_in0;
assign _T_19 = _T_18[7:0]; // ??
assign _T_20 = _T_19 - io_in1;
assign _T_21 = $unsigned(_T_20); // ??
assign _T_22 = _T_21[7:0]; // ??

In order to keep the carry you should use the expanding operators +& and -&.
io.p_out := io.in0 +& io.in0 -& io.in1
https://chisel.eecs.berkeley.edu/doc/chisel-cheatsheet3.pdf

Related

How to Overcome "warning: Port 8 (Destination) of instruction_reg expects 8 bits, got 1." in verilog?

My task is to implement a Processor with Data Memory using verilog. Instructions are hard coded (32 bit instructions). I have completed inserting a Data Memory.
For load and store instructions
But when complied i get- "warning: Port 8 (Destination) of instruction_reg expects 8 bits, got 1."
This a verilog code for a instruction set architecture
<pre><code>
//ALU created
module ALU(out,DATA1,DATA2,Select); //module for ALU
input [7:0]DATA1,DATA2;//8 bit data inputs
input [2:0] Select;//three bit selection
output [7:0]out;//8 bit data output
reg out;//outputt register
always#(DATA1,DATA2,Select)
begin
case(Select)
3'b000: out=DATA1;//forward
3'b001: out=DATA1+DATA2;//add
3'b010: out=DATA1 & DATA2;//and
3'b011: out=DATA1| DATA2; //or
endcase
end
endmodule
//here no need of its test bench
//registerFile created in part2
module Register(clk,busy_wait,INaddr,IN,OUT1addr,OUT1,OUT2addr,OUT2);
input clk;
input [2:0] INaddr;
input [7:0] IN;
input [2:0] OUT1addr;
output[7:0] OUT1;
input [2:0] OUT2addr;
output[7:0] OUT2;
input busy_wait; //new
reg [7:0] reg0, reg1, reg2, reg3,reg4,reg5,reg6,reg7;
assign OUT1 = OUT1addr == 0 ? reg0 :
OUT1addr == 1 ? reg1 :
OUT1addr == 2 ? reg2 :
OUT1addr == 3 ? reg3 :
OUT1addr == 4 ? reg4 :
OUT1addr == 5 ? reg5 :
OUT1addr == 6 ? reg6 :
OUT1addr == 7 ? reg7 : 0;
assign OUT2 = OUT2addr == 0 ? reg0 :
OUT2addr == 1 ? reg1 :
OUT2addr == 2 ? reg2 :
OUT2addr == 3 ? reg3 :
OUT2addr == 4 ? reg4 :
OUT2addr == 5 ? reg5 :
OUT2addr == 6? reg6 :
OUT2addr == 7 ? reg7 : 0;
always #(negedge clk)
begin
//check weather it is not busy
if (!busy_wait) begin
case(INaddr)
3'b000: reg0=IN;
3'b001: reg1=IN;
3'b010: reg2=IN;
3'b011: reg3=IN;
3'b100: reg4=IN;
3'b101: reg5=IN;
3'b110: reg6=IN;
3'b111: reg7=IN;
endcase
end
end
endmodule
//we need control unit
//we need twos compliment when substractor is called
module twos_compliment(IN,OUT); //twos complement
input [7:0] IN;
output signed [7:0] OUT;
assign OUT=-IN;
endmodule
//multiplexer is used to select value or compliment
module multiplex(IN1,IN2,OUT,SELECT); //multiplexer
input [7:0] IN1,IN2;
input SELECT;
output [7:0] OUT;
assign OUT = (SELECT) ? IN2 : IN1 ;
endmodule
//program counter is needed
module counter(clk,reset,busy_wait,addr); //module program counter
input clk,reset;
output [31:0] addr;
reg addr;
input busy_wait;
//in hardcoded instructions Memroy start is hexadecimal 00000000
always #(reset) begin
addr = 32'h00000000;
end
always #(negedge clk) begin
//now we have to check busy wait also
if(~reset && !busy_wait)
begin
addr = addr + 1;//addr is incremented by 1
end
else if (busy_wait) begin
addr <= addr ;
end
end
endmodule
//control unit
//input should be instruction opcode
//output should be select for alu and input to muxes
module CU(Instruction,busy_wait,opcode,SELECT,mulx1,mulx2,memRead,memWrite,regWrite,Destination,address); //control unit
input [7:0] opcode;
input [31:0] Instruction;
input [7:0] Destination;
//input [31:0] Instruction_code;//to extract load or Store Adress the Instruction code [23-16]
output [2:0] SELECT;
output mulx1,mulx2;
input busy_wait; //new
output memRead; //new
output memWrite;//new
output regWrite;//new
output [7:0] address;//new
reg mulx1,mulx2,memRead,memWrite,regWrite,address;
assign SELECT = opcode [2:0]; //select should be opcodes last three bits for alu
always #(opcode) begin
case(opcode)
8'b00000000:begin //for mov
mulx1 = 1'b1;
mulx2 = 1'b0;
end
8'b00000001:begin //for add
mulx1 = 1'b1;
mulx2 = 1'b0;
end
8'b00001001:begin //sub
mulx1 = 1'b1;
mulx2 = 1'b1;
end
8'b00000010:begin //and
mulx1 = 1'b1;
mulx2 = 1'b0;
end
8'b00000011:begin //or
mulx1 = 1'b1;
mulx2 = 1'b0;
end
8'b00001000:begin //for loadImmediate
mulx1 = 1'b0;
end
/*4'b0101:
begin
memRead = 1'b0;
memWrite = 1'b1;
address = instruction[23:16];
$display("oper = store");
end
// store to memory
*/
8'b00000101:begin //for store to Data memory(selected 00000101)
memRead = 1'b0;
memWrite = 1'b1;
assign address = Destination;
mulx1 = 1'b1;
mulx2 = 1'b1;
end
/*4'b0100:
// load from memory
begin
memWrite = 1'b0;
memRead = 1'b1;
address = instruction[7:0];
$display("oper = load");
end
*/
8'b00000100:begin //for load To register From Data memory (selected 00000100)
memWrite = 1'b0;
memRead = 1'b1;
assign address = Instruction[7:0];
mulx1 = 1'b1;
mulx2 = 1'b1;
end
default :
begin
memWrite = 1'b0;
memRead = 1'b0;
end
endcase
end
endmodule
//instruction memory 32 bits instead of memory
module instruction_mem(Read_addr,Instruction_code);
output [31:0] Instruction_code;
reg Instruction_code;
input [31:0] Read_addr;
always #(Read_addr) begin
case(Read_addr)
/*32'h00000000: Instruction_code = 32'b00001000 00000 100 00000000 11111111;// loadi 4 X 0xFF(255)
32'h00000001: Instruction_code = 32'b00001000 00000 110 00000000 10101010;// loadi 6 X 0xAA(170)
32'h00000002: Instruction_code = 32'b00001000 00000 011 00000000 10111011;// loadi 3 X 0xBB(187)
32'h00000003: Instruction_code = 32'b00000001 00000 101 00000 110 00000 011;// add 5 6 3
32'h00000004: Instruction_code = 32'b00000010 00000 001 00000 100 00000 101;// and 1 4 5
32'h00000005: Instruction_code = 32'b00000011 00000 010 00000 001 00000 110;// or 2 1 6
32'h00000006: Instruction_code = 32'b00000000 00000 111 00000 000 00000 010;// mov 7 x 2
32'h00000007: Instruction_code = 32'b00001001 00000 100 00000 111 00000 011;// sub 4 7 3
32'h00000008: Instruction_code = 32'b00000101 00000000 00000 000 00000 100; // store 0, X, 4
32'h00000009: Instruction_code = 32'b00000100 00000101 00000 000 00000 000; // load 5, X, 0*/
/*Hard coded instructions for Processor without memry is commented*/
/*32'h00000000: Instruction_code = 32'b00001000000001000000000011111111;// loadi 4 X 0xFF(255)
32'h00000001: Instruction_code = 32'b00001000000001100000000010101010;// loadi 6 X 0xAA(170)
32'h00000002: Instruction_code = 32'b00001000000000110000000010111011;// loadi 3 X 0xBB(187)
32'h00000003: Instruction_code = 32'b00000001000001010000011000000011;// add 5 6 3
32'h00000004: Instruction_code = 32'b00000010000000010000010000000101;// and 1 4 5
32'h00000005: Instruction_code = 32'b00000011000000100000000100000110;// or 2 1 6
32'h00000006: Instruction_code = 32'b00000000000001110000000000000010;// mov 7 x 2
32'h00000007: Instruction_code = 32'b00001001000001000000011100000011;// sub 4 7 3*/
//new instructions
32'h00000000: Instruction_code = 32'b00000101000000000000000000000100; // store 0, X, 4
32'h00000001: Instruction_code = 32'b00000100000001010000000000000000; // load 5, X, 0
endcase
end
endmodule
//inside the control unit a opcode should be divided in instruction reg
module instruction_reg(Instruction,clk,OPCODE,OUT1addr,OUT2addr,INaddr,Immediate,Destination);
input [31:0] Instruction;
input clk;
output[2:0] OUT1addr,OUT2addr,INaddr;
output [7:0] OPCODE,Immediate,Destination;
assign INaddr = Instruction[18:16];
assign OPCODE = Instruction[31:24];//31-24 taken declared as op code
assign Immediate = Instruction[7:0];//immediate value is 7-0
assign OUT1addr = Instruction[2:0]; //output1addr addredd of output data by the registerFile
assign OUT2addr = Instruction[10:8];
assign Destination=Instruction[23:16];//new
endmodule
//data memory
module data_mem(
clk,
rst,
read,
write,
address,
write_data,
read_data,
busy_wait
);
input clk;
input rst;
input read;
input write;
input[7:0] address;
input[7:0] write_data;
output[7:0] read_data;
output busy_wait;
reg[7:0] read_data;
reg busy_wait,clkMem=1'b0;
integer i;
// Declare memory 256x8 bits
reg [7:0] memory_array [255:0];
//reg [7:0] memory_ram_q [255:0];
always #(posedge rst)
begin
if (rst)
begin
for (i=0;i<256; i=i+1)
memory_array[i] <= 0;
end
end
always #1 clkMem = ~clkMem;
always #(posedge clkMem)
begin
if (write && !read && !busy_wait)
begin
busy_wait <= 1;
// artificially delay 100 cycles
repeat(10)
begin
#(posedge clk);
end
$display("writing to memory");
memory_array[address] = write_data;
busy_wait <= 0;
end
if (!write && read && !busy_wait)
begin
busy_wait <= 1;
// artificially delay 100 cycles
repeat(10)
begin
#(posedge clk);
end
$display("reading from memory");
read_data = memory_array[address];
busy_wait <= 0;
end
end
endmodule
//test bench
module for_processor_test();
wire [2:0] SELECT,OUT1addr,OUT2addr,INaddr;
wire mux1OUT,mux2OUT;
reg clk,reset,reset_reg;
wire [31:0] Read_addr,Instruction_code;
wire [7:0] OPCODE,Immediate,OUT1,OUT2,RESULT,twosComplement,mux2out,mux1out;
counter c1(clk,reset,busy_wait,Read_addr);
instruction_mem instruct_mem1(Read_addr,Instruction_code);
instruction_reg instruct_reg1(Instruction_code,clk,OPCODE,OUT1addr,OUT2addr,INaddr,Immediate,Destination);
CU cu1(Instruction_code,busy_wait,OPCODE,SELECT,mulx1,mulx2,memRead,memWrite,regWrite,Destination,address);
//CU cu1(Instruction_code,busy_wait,opcode,SELECT,mulx1,mulx2,memRead,memWrite,regWrite,address);
//CU myCU(busy_wait,instruction, out_addr1, out_addr2, in_addr, select, data2_compli_control, immediate_control, immediate_value, memRead,memWrite,regWrite,address);
//(opcode,SELECT,mulx1,mulx2,memRead,memWrite,regWrite)
Register regfile(clk,busy_wait,INaddr,RESULT,OUT1addr,OUT1,OUT2addr,OUT2);
twos_compliment tcmplmnt(OUT1,twosComplement);
multiplex mulx2(OUT1,twosComplement,mux2out,mux2OUT);
multiplex mulx1(Immediate,mux2out,mux1out,mux1OUT);
ALU alu(RESULT,mux1out,OUT2,SELECT);
data_mem mdata_mem(clk,rst,memRead,memWrite,address,write_data,read_data,busy_wait);
always #10 clk = ~clk;
initial begin
clk = 0;
reset = 1;
reset = 0;
reset_reg = 1;
reset_reg = 0;
#160
$finish;
end
initial begin
while(1) begin
#10 $display("INSTRUCTION=%b RESULT=%d clock=%d",Instruction_code,RESULT,clk);
//#20 $display("INSTRUCTION=%b RESULT=%d clock=%d",Instruction_code,RESULT,clk);
end
end
endmodule
</code></pre>
In module for_processor_test you have not declared Destination. Verilog is a pretty liberal language (by default), so it has implicitly declared a wire called Destination for you. However, this implicit wire will be only 1 bit wide. Hence, your error message.
If you want to tighten up this liberal behaviour (you do), then you can add this compile directive:
`default_nettype none
Had you done this, you would have got a more descriptive error message.

Writing Fibonacci Sequence Elegantly Python

I am trying to improve my programming skills by writing functions in multiple ways, this teaches me new ways of writing code but also understanding other people's style of writing code. Below is a function that calculates the sum of all even numbers in a fibonacci sequence up to the max value. Do you have any recommendations on writing this algorithm differently, maybe more compactly or more pythonic?
def calcFibonacciSumOfEvenOnly():
MAX_VALUE = 4000000
sumOfEven = 0
prev = 1
curr = 2
while curr <= MAX_VALUE:
if curr % 2 == 0:
sumOfEven += curr
temp = curr
curr += prev
prev = temp
return sumOfEven
I do not want to write this function recursively since I know it takes up a lot of memory even though it is quite simple to write.
You can use a generator to produce even numbers of a fibonacci sequence up to the given max value, and then obtain the sum of the generated numbers:
def even_fibs_up_to(m):
a, b = 0, 1
while a <= m:
if a % 2 == 0:
yield a
a, b = b, a + b
So that:
print(sum(even_fibs_up_to(50)))
would output: 44 (0 + 2 + 8 + 34 = 44)

How to generate a sum and carry with Chisel in one line?

Is it possible to generate sum and carry in one line in Chisel similar to this code in Verilog?
module Adder_with_carry(
input [3:0] A,
input [3:0] B,
input Carry_in,
output [3:0] Sum,
output Carry_out
);
assign {Carry_out, Sum} = A + B + Carry_in;
endmodule
I am using this code
class Adder extends Module{
val io = new Bundle{
val a = UInt(INPUT, 3)
val b = UInt(INPUT, 3)
val carry_in = UInt (INPUT, 1)
val sum = UInt (OUTPUT, 2)
val carry_out = UInt(OUTPUT, 1)
}
val SUM = io.a + io.b + io.carry_in;
io.carry_out := SUM(2)
io.sum := SUM(1,0)
}
But I think it will be more convenient if there is a one-liner for this.

How to get working variables out of a function in F#

I have a function in F# , like:
let MyFunction x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
y
Basically, MyFunction takes an input x and returns y. However, in the process of calculation, there are a few working variables (intermediate variables), and due to the nature of my work (civil engineering), I need to report all intermediate results. How should I store all working variables of the function ?
I'm not exactly sure what kind of "report" your are expecting. Is this a log of intermediate values ? How long time this log should be kept ? etc. etc This is my attempt from what I understand. It is not ideal solution because it allows to report values of intermediate steps but without knowing exactly which expression has generated the intermediate value (I think that you would like to know that a value n was an output of workingVariable1 = x + 1 expression).
So my solution is based on Computation Expressions. Computation expression are a kind of F# "monads".
First you need to define a computation expression :
type LoggingBuilder() =
let log p = printfn "intermediate result %A" p
member this.Bind(x, f) =
log x
f x
member this.Return(x) =
x
Next we create an instance of computation expression builder :
let logIntermediate = new LoggingBuilder()
Now you can rewrite your original function like this:
let loggedWorkflow x =
logIntermediate
{
let! workingVariable1 = x + 1
let! workingVariable2 = workingVariable1 + 1
let! y = workingVariable2 + 1
return y,workingVariable1,workingVariable2
}
If you run loggedWorkflow function passing in 10 you get this result :
> loggedWorkflow 10;;
intermediate result 11
intermediate result 12
intermediate result 13
val it : int * int * int = (13, 11, 12)
As I said your intermediate values are logged, however you're not sure which line of code is responsible for.
We could however enchance a little bit to get the FullName of the type with a corresponding line of code. We have to change a little our computation expression builder :
member this.Bind(x, f) =
log x (f.GetType().FullName)
f x
and a log function to :
let log p f = printfn "intermediate result %A %A" p f
If you run again loggedWorkflow function passing in 10 you get this result (this is from my script run in FSI) :
intermediate result 11 "FSI_0003+loggedWorkflow#34"
intermediate result 12 "FSI_0003+loggedWorkflow#35-1"
intermediate result 13 "FSI_0003+loggedWorkflow#36-2"
This is a hack but we get some extra information about where the expressions like workingVariable1 = x + 1 were definied (in my case it is "FSI_") and on which line of code (#34, #35-1). If your code changes and this is very likely to happen, your intermediate result if logged for a long time will be false. Note that I have not tested it outside of FSI and don't know if lines of code are included in every case.
I'm not sure if we can get an expression name (like workingVariable1 = x + 1) to log from computation expression. I think it's not possible.
Note: Instead of log function you coud define some other function that persist this intermediate steps in a durable storage or whatever.
UPDATE
I've tried to came up with a different solution and it is not very easy. However I might have hit a compromise. Let me explain. You can't get a name of value is bound to inside a computation expression. So we are not able to log for example for expression workingVariable1 = x + 1 that "'workingVariable1' result is 2". Let say we pass into our computation expression an extra name of intermediate result like that :
let loggedWorkflow x =
logIntermediate
{
let! workingVariable1 = "wk1" ## x + 1
let! workingVariable2 = "wk2" ## workingVariable1 + 1
let! y = "y" ## workingVariable2 + 1
return y,workingVariable1,workingVariable2
}
As you can see before ## sign we give the name of the intermediate result so let! workingVariable1 = "wk1" ## x + 1 line will be logged as "wk1".
We need then an extra type which would store a name and a value of the expression :
type NamedExpression<'T> = {Value:'T ; Name: string}
Then we have to redefine an infix operator ## we use une computation expression :
let (##) name v = {Value = v; Name = name}
This operator just takes left and right part of the expression and wraps it within NamedExpression<'T> type.
We're not done yet. We have to modify the Bind part of our computation expression builder :
member this.Bind(x, f) =
let {Name = n; Value = v} = x
log v n
f v
First we deconstruct the NamedExpression<'T> value into name and wraped value. We log it and apply the function f to the unwrapped value v. Log function looks like that :
let log p n = printfn "'%s' has intermediate result of : %A" n p
Now when you run the workflow loggedWorkflow 10;; you get the following result :
'wk1' has intermediate result of : 11
'wk2' has intermediate result of : 12
'y' has intermediate result of : 13
Maybe there are better way to do that, something with compiler services or so, but this is the best attempt I could do so far.
If I understand you correctly, then there are several options:
let MyFunction1 x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
y,workingVariable1,workingVariable2
MyFunction1 2 |> printfn "%A"
type OneType()=
member val Y = 0 with get,set
member val WV1 = 0 with get,set
member val WV2 = 0 with get,set
override this.ToString() =
sprintf "Y: %d; WV1: %d; WV2: %d\n" this.Y this.WV1 this.WV2
let MyFunction2 x =
let workingVariable1 = x + 1
let workingVariable2 = workingVariable1 + 1
let y = workingVariable2 + 1
new OneType(Y=y,WV1=workingVariable1,WV2=workingVariable2)
MyFunction2 2 |> printfn "%A"
Out:
(5, 3, 4)
Y: 5; WV1: 3; WV2: 4
http://ideone.com/eYNwYm
In the first function uses the tuple:
https://msdn.microsoft.com/en-us/library/dd233200.aspx
The second native data type.
https://msdn.microsoft.com/en-us/library/dd233205.aspx
It's not very "functional" way, but you can use mutable variable to store intermediate results:
let mutable workingVariable1 = 0
let mutable workingVariable2 = 0
let MyFunction x =
workingVariable1 <- x + 1
workingVariable2 <- workingVariable1 + 1
let y = workingVariable2 + 1
y

Verilog Code: Output Malfunction

The following code is meant to output a 1 in the case of wires S1 and X being asserted and wire S0 being deasserted. However, when I run the wave form, the output is constantly 0.
The logic equations governing the wires are:
S1 = (S0 & ~X) | (S1 & ~S0 & X)
S0 = X
O = (S1 & S0)
Is there a problem with my code:
module Dff1(D, clk, Q, Qbar);
input D, clk;
output reg Q;
output Qbar;
initial begin
Q = 0;
end
assign Qbar = ~Q;
always #(posedge clk)
Q = D;
endmodule
module Mod1 (clk, X, O);
input clk, X;
output O;
wire S1, S0, Q1, Q0, Q1bar, Q0bar;
assign S1 = (S0 & ~X) | (S1 & ~S0 & X);
Dff1 C1(S1, clk, Q1, Q1bar);
assign S0 = X;
Dff1 C0(S0, clk, Q0, Q0bar);
assign O = (S1 & S0);
endmodule
module test_bench ();
wire clk;
reg osc;
reg [1:0] R;
reg Seqinput;
integer num;
initial begin
osc = 0;
num = 0;
Seqinput = 0;
end
initial begin
$dumpfile("dump.vcd");
$dumpvars;
#20000 $finish;
end
always begin
#10 osc = ~osc;
num = (num >= 7) // counter incremented by 1 from 0..7
? 0 : (num + 1);
if ((num % 2) == 0) begin // every other time step
R = $random % 2; // $random generates a 32-bit signed
// random number
// -1 <= $random % 2 <= 1
if (R > 0)
Seqinput = 1; // input is 1
else
Seqinput = 0; // input is 0
end
end
assign clk=osc;
wire Out1;
Mod1 Mod1instance(clk, Seqinput, Out1);
endmodule
Explained with substitution:
S1 = (S0 & ~X) | (S1 & ~S0 & X) sub S0 with X
S1 = ((X) & ~X) | (S1 & ~(X) & X) X & ~X == 0
S1 = ( 0 ) | ( S1 & 0 ) S1 & 0 == 0;
S1 = ( 0 ) | ( 0 )
S1 = 0
Since the assignment of S1 dependent on its current value, it is considered asynchronous feedback logic. This is normally something you don't want to do. I believe the real equation you want is:
S1 = (Q0 & ~X) | (Q1 & ~Q0 & X)
This makes the code synchronous and predictable. Q1 and Q0 are the previous clocked values of S1 and S0 respectively.
Also, it is important to use non-blocking assignments when assigning (<=) flops. Verilog is a non-determent simulator. This means operations scheduled in the same region can happen in any order. Using non-blocking on a flop moves the assignment to the NBA region while its evaluation in kept in the active region.
always #(posedge clk)
Q <= D;