How to Overcome "warning: Port 8 (Destination) of instruction_reg expects 8 bits, got 1." in verilog? - warnings
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.
Related
How to add 3 number together?
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
LINT-34 (warning) In design '%s', three-state bus '%s' has non three- state driver '%s'
I am trying to synthesize a program I created in Verilog using Design Vision. I get multiple of the following warnings: Warning: In design 'mergeTOP', three-state bus 'state[0]' has non three-state driver 'u1/state_reg[0]/Q'. (LINT-34) Warning: In design 'mergeTOP', three-state bus 'temp_in5[0]' has non three-state driver 'u1/temp_in05_reg[0]/Q'. (LINT-34) DESCRIPTION Synopsys libraries contain descriptions of three-state driving pins on components. Synopsys tools classify a net as a three-state net if it is driven by at least one pin that has this three-state attribute. Normally, if there are multiple drivers on such nets, it is assumed that all driving pins should be three-state drivers, for correct opera- tion of the three-state bus. This warning message indicates a situa- tion where at least one non-three-state driver appears on a three-state net. /*======Declarations===============================*/ module controller (clock, reset, start, state, temp_in1, temp_in2, temp_in3, temp_in4, temp_in5, done, temp_out1, temp_out2, temp_out3, temp_out4, temp_out5, out, in); /*-----------Inputs--------------------------------*/ input clock, reset, start; input [255:0] in; input [255:0] temp_out1, temp_out2, temp_out3, temp_out4, temp_out5; /*-----------Outputs--------------------------------*/ output [5:0] state; // output [255:0] temp_in01, temp_in02, temp_in03, temp_in04, temp_in05; output done; output [255:0] out; output [255:0] temp_in1, temp_in2, temp_in3, temp_in4, temp_in5; /*----------------Nets and Registers----------------*/ reg [5:0] state, n_state; reg [255:0] temp_in01, temp_in02, temp_in03, temp_in04, temp_in05; reg done; reg [255:0] out; always#(posedge clock) // at the posedge of the clock the current state changes based on whether reset is active or the next state determined by the logic. begin if (!reset) // if the active low reset is triggered the state is set to 0. state <= 6'b000000; else // if reset is high or inactive the current state gets the value of the next state. state <= n_state; end always#* begin // control path case (state) 6'b000000: begin // state S0, wait for input. if (start == 1) n_state = 6'b000001; else n_state = 6'b000000; end 6'b000001: begin // state S1 n_state = 6'b000010; end 6'b000010: begin // state S2 n_state = 6'b000100; end 6'b000100: begin // state S3 n_state = 6'b001000; end 6'b001000: begin // state S4 n_state = 6'b010000; end 6'b010000: begin // state S5 n_state = 6'b100000; end 6'b100000: begin // state S5 n_state = 6'b100000; end default: n_state = 6'b000000; endcase end always#(posedge clock) begin if (!reset) begin temp_in01 <= 0; out <= 0; done <= 0; end else begin case(state) 6'b000000: begin temp_in01 <= in; out <= in; done <= 0; end 6'b000001: begin temp_in02 <= temp_out1; out <= temp_out1; done <= 0; end 6'b000010: begin temp_in03 <= temp_out2; out <= temp_out2; done <= 0; end 6'b000100: begin temp_in04 <= temp_out3; out <= temp_out3; done <= 0; end 6'b001000: begin temp_in05 <= temp_out4; out <= temp_out4; done <= 0; end 6'b010000: begin out <= temp_out5; done <= 0; end 6'b100000: begin out <= out; done <= 1; end default: begin out <= out; done <= 0; end endcase end end assign temp_in5 = temp_in05; assign temp_in4 = temp_in04; assign temp_in3 = temp_in03; assign temp_in2 = temp_in02; assign temp_in1 = temp_in01; endmodule ` /*======Declarations===============================*/ module mergeTOP (clock, reset, start, in, out, done); /*-----------Inputs--------------------------------*/ input [255:0] in; input clock, reset, start; /*-----------Outputs--------------------------------*/ output [255:0] out; output done; /*----------------Nets and Registers----------------*/ // reg [255:0] out; // reg done; wire [5:0] state; wire [255:0] temp_out1, temp_out2, temp_out3, temp_out4, temp_out5; wire [255:0] temp_in1, temp_in2, temp_in3, temp_in4, temp_in5; controller u1 (.clock(clock), .reset(reset), .start(start), .state(state), .done(done), .out(out), .in(in), .temp_in1(temp_in1), .temp_in2(temp_in2), .temp_in3(temp_in3), .temp_in4(temp_in4), .temp_in5(temp_in5), .temp_out1(temp_out1), .temp_out2(temp_out2), .temp_out3(temp_out3), .temp_out4(temp_out4), .temp_out5(temp_out5) ); merge1 #(16) u2 (.in(temp_in1),.out(temp_out1),.state(state)); merge1 #(32) u3 (.in(temp_in2),.out(temp_out2),.state(state)); merge1 #(64) u4 (.in(temp_in3),.out(temp_out3),.state(state)); merge1 #(128) u5 (.in(temp_in4),.out(temp_out4),.state(state)); merge1 #(256) u6 (.in(temp_in5),.out(temp_out5),.state(state)); endmodule
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;
Find the combinations of 2 1's in a binary number
We have a binary number and we need to generate combination of 2 1's from the given number. If given such a combination of 2 1's we should be able to produce the next combination. Example:- Given vector : 10101111 Given combination : 10100000 output : 10001000 Given vector : 10101111 Given combination : 10001000 output : 10000100 Given vector : 10101111 Given combination : 10000010 output : 10000001 Given vector : 10101111 Given combination : 10000001 output : 00101000 Given vector : 10101111 Given combination : 00101000 output : 00100100 Edit: Once the 2nd 1 reaches the last 1 in the given binary number, the 1st 1 is incremented(set to next '1' in the binary number and the 2nd '1' is made the '1' that comes after the 1st '1'(as in eg 4)) This is to be done in hardware so it should not be computationally complex. How can we design this module in VHDL.
Here is some asynchronous code that will do the job: library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity nex2ones is Port ( vector : in STD_LOGIC_VECTOR (1 to 8); combo1 : in STD_LOGIC_VECTOR (1 to 8); combo2 : out STD_LOGIC_VECTOR (1 to 8); error : out STD_LOGIC); end nex2ones; architecture Behavioral of nex2ones is type int_array_8 is array (1 to 8) of integer range 0 to 8; begin process (vector,combo1) variable ones_ixs : int_array_8; variable first_combo1_ix : integer range 0 to 8 := 0; variable second_combo1_ix: integer range 0 to 8 := 0; variable first_combo1_k : integer range 0 to 9 := 0; variable second_combo1_k : integer range 0 to 9 := 0; variable k : integer range 1 to 9; begin ones_ixs := (others => 0); -- indices of 1s in vector combo2 <= (others => '0'); k := 1; first_combo1_ix := 0; second_combo1_ix := 0; first_combo1_k := 0; -- corresponding ptr to ones_ixs second_combo1_k := 0; error <= '0'; for j in 1 to 8 loop if combo1(j) = '1' then if first_combo1_ix = 0 then first_combo1_ix := j; first_combo1_k := k; else second_combo1_ix := j; second_combo1_k := k; end if; end if; if vector(j) = '1' then ones_ixs(k) := j; k := k + 1; end if; end loop; if k > 1 then k := k - 1; end if; -- point to last nonzero index if (first_combo1_ix = 0 or second_combo1_ix = 0) --or (first_combo1_ix = ones_ixs(k-1) and second_combo1_ix = ones_ixs(k)) or (k < 2) then error <= '1'; else -- no error proceed if second_combo1_ix = ones_ixs(k) then -- can't slide 2nd anymore if (second_combo1_k - first_combo1_k) > 1 then -- is 1st movable combo2(ones_ixs(first_combo1_k + 1)) <= '1'; -- move 1st if (second_combo1_k - first_combo1_k) > 2 then -- is 2nd movable combo2(ones_ixs(first_combo1_k + 2)) <= '1'; -- move 2nd else combo2(ones_ixs(second_combo1_k)) <= '1'; -- leave 2nd be end if; else error <= '1'; -- no mas end if; else combo2(ones_ixs(first_combo1_k)) <= '1'; -- leave 1st be combo2(ones_ixs(second_combo1_k + 1)) <= '1'; -- next end if; end if; end process; end Behavioral; Testbench output: ps vector combo1 combo2 error 0 00000000 00000000 00000000 1 100000 10101111 10100000 10001000 0 200000 10101111 10001000 10000100 0 300000 10101111 10000010 10000001 0 400000 10101111 10000001 00101000 0 500000 10101111 00101000 00100100 0 600000 10101111 00100100 00100010 0 700000 10101111 00000011 00000000 1 800000 11001110 00000110 00000000 1 900000 10001110 00001010 00000110 0 1000000 11001110 00001010 00000110 0
Lua: print integer as a binary
How can I represent integer as Binary? so I can print 7 as 111
You write a function to do this. num=7 function toBits(num) -- returns a table of bits, least significant first. local t={} -- will contain the bits while num>0 do rest=math.fmod(num,2) t[#t+1]=rest num=(num-rest)/2 end return t end bits=toBits(num) print(table.concat(bits)) In Lua 5.2 you've already have bitwise functions which can help you ( bit32 ) Here is the most-significant-first version, with optional leading 0 padding to a specified number of bits: function toBits(num,bits) -- returns a table of bits, most significant first. bits = bits or math.max(1, select(2, math.frexp(num))) local t = {} -- will contain the bits for b = bits, 1, -1 do t[b] = math.fmod(num, 2) num = math.floor((num - t[b]) / 2) end return t end
There's a faster way to do this that takes advantage of string.format, which converts numbers to base 8. It's trivial to then convert base 8 to binary. --create lookup table for octal to binary oct2bin = { ['0'] = '000', ['1'] = '001', ['2'] = '010', ['3'] = '011', ['4'] = '100', ['5'] = '101', ['6'] = '110', ['7'] = '111' } function getOct2bin(a) return oct2bin[a] end function convertBin(n) local s = string.format('%o', n) s = s:gsub('.', getOct2bin) return s end If you want to keep them all the same size, then do s = string.format('%.22o', n) Which gets you 66 bits. That's two extra bits at the end, since octal works in groups of 3 bits, and 64 isn't divisible by 3. If you want 33 bits, change it to 11. If you have the BitOp library, which is available by default in LuaJIT, then you can do this: function convertBin(n) local t = {} for i = 1, 32 do n = bit.rol(n, 1) table.insert(t, bit.band(n, 1)) end return table.concat(t) end But note this only does the first 32 bits! If your number is larger than 2^32, the result wont' be correct.
function bits(num) local t={} while num>0 do rest=num%2 table.insert(t,1,rest) num=(num-rest)/2 end return table.concat(t) end Since nobody wants to use table.insert while it's useful here
Here is a function inspired by the accepted answer with a correct syntax which returns a table of bits in wriiten from right to left. num=255 bits=8 function toBits(num, bits) -- returns a table of bits local t={} -- will contain the bits for b=bits,1,-1 do rest=math.fmod(num,2) t[b]=rest num=(num-rest)/2 end if num==0 then return t else return {'Not enough bits to represent this number'}end end bits=toBits(num, bits) print(table.concat(bits)) >>11111111
function reverse(t) local nt = {} -- new table local size = #t + 1 for k,v in ipairs(t) do nt[size - k] = v end return nt end function tobits(num) local t={} while num>0 do rest=num%2 t[#t+1]=rest num=(num-rest)/2 end t = reverse(t) return table.concat(t) end print(tobits(7)) # 111 print(tobits(33)) # 100001 print(tobits(20)) # 10100
local function tobinary( number ) local str = "" if number == 0 then return 0 elseif number < 0 then number = - number str = "-" end local power = 0 while true do if 2^power > number then break end power = power + 1 end local dot = true while true do power = power - 1 if dot and power < 0 then str = str .. "." dot = false end if 2^power <= number then number = number - 2^power str = str .. "1" else str = str .. "0" end if number == 0 and power < 1 then break end end return str end May seem more verbose but it is actually faster than other functions that use the math library functions. Works with any number, be it positive/negative/fractional...
local function tobits(num, str) -- tail call str = str or "B" if num == 0 then return str end return tobits( num >> 1 , -- right shift ((num & 1)==1 and "1" or "0") .. str ) end
This function uses a lookup table to print a binary number extracted from a hex representation. All using string manipulation essentially. Tested in lua 5.1. local bin_lookup = { ["0"] = "0000", ["1"] = "0001", ["2"] = "0010", ["3"] = "0011", ["4"] = "0100", ["5"] = "0101", ["6"] = "0110", ["7"] = "0111", ["8"] = "1000", ["9"] = "1001", ["A"] = "1010", ["B"] = "1011", ["C"] = "1100", ["D"] = "1101", ["E"] = "1110", ["F"] = "1111" } local print_binary = function(value) local hs = string.format("%.2X", value) -- convert number to HEX local ln, str = hs:len(), "" -- get length of string for i = 1, ln do -- loop through each hex character local index = hs:sub(i, i) -- each character in order str = str .. bin_lookup[index] -- lookup a table str = str .. " " -- add a space end return str end print(print_binary(45)) #0010 1101 print(print_binary(65000)) #1111 1101 1110 1000
This maybe not work in lua that has no bit32 library function toBinary(number, bits) local bin = {} bits = bits - 1 while bits >= 0 do --As bit32.extract(1, 0) will return number 1 and bit32.extract(1, 1) will return number 0 --I do this in reverse order because binary should like that table.insert(bin, bit32.extract(number, bits)) bits = bits - 1 end return bin end --Expected result 00000011 print(table.concat(toBinary(3, 8))) This need at least lua 5.2 (because the code need bit32 library)
As by Dave, but with filled empty bits: local function toBits(num, bits) -- returns a table of bits, least significant first. local t={} -- will contain the bits bits = bits or 8 while num>0 do rest=math.fmod(num,2) t[#t+1]=rest num=math.floor((num-rest)/2) end for i = #t+1, bits do -- fill empty bits with 0 t[i] = 0 end return t end for i = 0, 255 do local bits = toBits(i) print(table.concat(bits, ' ')) end Result: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 ... 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1