binary to bcd verilog output is always x - verilog

I have a binary to bcd convertor module that uses the shift add 3 algorithm as follows :
module BCD(
input wire [7:0] binary,
output wire [3:0] Hundreds,
output wire [3:0] Tens,
output wire [3:0] Ones
);
integer i;
reg [11:0] bcd;
initial begin
bcd = 12'b000000000000;
for(i=7;i>=0;i=i-1) begin
bcd[11:0] = { bcd[10:0], binary[i] };
if(bcd[3:0] >= 5) bcd[3:0] = bcd[3:0] + 2'b11;
if(bcd[7:4] >= 5) bcd[7:4] = bcd[7:4] + 2'b11;
end
end
assign Hundreds = bcd[11:8];
assign Tens = bcd[7:4];
assign Ones = bcd[3:0];
endmodule;
and a Test bench for it as follows :
module BCD_Testbunch();
reg [7:0] binary;
wire [3:0] bcd_u;
wire [3:0] bcd_t;
wire [3:0] bcd_h;
integer i;
initial begin
binary = 8'b00000000;
$monitor("t = %g\t || Binary =%b (%d) BCD = %d %d %d",$time,binary,binary,bcd_h,bcd_t,bcd_u);
for(i=1;i<=8'b11111111;i=i+1)
#5 binary = binary + 1;
end
BCD B (binary,bcd_h,bcd_t,bcd_u);
endmodule;
yet my bcd output is always 0 x x whatever the value of the binary input

As #mkrieger1 pointed out in comments I changed the initial to always #(*) in bcd module And everything is working now

Related

Verilog Temporary Variable

I tried to make a CMP instruction in Verilog. To keep the result of the substraction, I declared a wire. This is what the code looks like (It is executed in an always statement).
wire [data_width:0] tmp_wire = reg_accumulator - reg_x;
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
Now Icarus Verilog complains about a syntax error and that reg_accumulator - reg_x is not an l-value:
cpu.v:149: syntax error
cpu.v:149: Syntax in assignment statement l-value.
And why does it complain? What would be the right approach to declare a temporary variable in a function / task?
module comparator(
input clk,
input [7:0] op_a,
input [7:0] op_b
);
reg f_zero;
reg f_carry;
function compare;
input [data_width-1:0] a;
input [data_width-1:0] b;
begin
wire [7:0] tmp_wire = reg_accumulator - reg_x;
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
end
endfunction
always #(posedge clk) begin
compare(op_a, op_b);
end
endmodule // comparator
Either you should use systemverilog and include this in a class or you can create a parameterized module:
module compare_zero_n_carry
# (
parameter DATA_WIDTH = 8
)
(zero, carry, a, b);
/* ports */
input [DATA_WIDTH-1:0] a; //.."reg_accumulator"
input [DATA_WIDTH-1:0] b; //.."reg_x"
output zero;
output carry;
wire [DATA_WIDTH-1:0] tmp_wire = a - b;
assign zero = (tmp_wire & {DATA_WIDTH{1'b1}}) == {DATA_WIDTH{1'b0}};
//..HERE IM NOT REALLY SURE WHAT IS THE LOGIC FOR THE CARRY,
//..IT SHOULD BE ONE BIT
assign carry = (tmp_wire & {1'b1,{(DATA_WIDTH-1){1'b0}}});
endmodule // compare_zero_n_carry
And instantiate it in the main comparator module as:
input clk;
input [DATA_WIDTH-1:0] op_a;
input [DATA_WIDTH-1:0] op_b;
wire f_zero;
wire f_carry;
reg f_zero_reg;
reg f_carry_reg;
compare_zero_n_carry
# (
.DATA_WIDTH (DATA_WIDTH)
)
compare_zero_n_carry_inst (
.a (op_a),
.b (op_b),
.zero (f_zero),
.carry (f_carry)
);
always # (posedge clk) begin
f_zero_reg <= f_zero;
f_carry_reg <= f_carry;
end
You cannot declare a wire inside the always block.
wire [7:0] tmp_wire = reg_accumulator - reg_x;
always #(posedge clk) begin
f_zero <= tmp_wire & 'hFF == 0;
f_carry <= tmp_wire & 'h100;
end

Always loop that does not assign the outputs

I am making an average that resets every period on EDA Playground. No errors are displayed on the simulator, Icarus Verilog, but the outputs are continually unassigned (which, of course, is not what I intended).
Here is my design:
module shift
(
input [13:0] in,
input clock,
output [31:0] sum,
output [14:0] avg);
integer reset;
reg [31:0] sum_reg;
reg [14:0] avg_reg;
always #(posedge clock)
if (reset == 8) begin
avg_reg = sum_reg >> 3;
sum_reg = 0;
reset = 0;
end else begin
sum_reg = sum_reg + in;
reset = reset + 1;
end
assign sum = sum_reg;
assign avg = avg_reg;
endmodule
Here is my testbench:
module shift_tb;
reg [13:0] in;
reg clock = 1'b0;
reg reset;
wire [31:0] sum;
wire [14:0] avg;
shift s
(
.in(in),
.clock(clock),
.sum(sum),
.avg(avg));
integer f;
initial begin
for (f = 9000; f < 10000; f = f + 10) begin
in = f;
$display("in = %d, sum = %d, avg = %d", in, sum, avg);
end
end
always
#1 clock = ~clock;
endmodule
What is wrong with this code?
One problem is reset is an integer that is initially x and stays that way. You need a way of initializing it to 0.
Another problem is your testbench for-loop has no delay. You should add #(nedgedge clk)

Modules in Verilog do not respond to input signals

My current task is to create a memory driver. The specific issue is that I have a shift register designed to concatenate four 8-bit words into one 32-bit and then send that to the output. The module works when being simulated by itself but it fails to respond when connected to other modules. Here's the code :
The shift register code :
module shiftReg (
data_8,
clk,
valid1,
rstn,
data_32,
valid_fifo,
count,
REGA,
REGB,
REGC,
REGD
);
input wire [7:0] data_8;
input wire valid1;
input wire clk;
input wire rstn;
output reg [31:0] data_32;
output reg valid_fifo;
output reg [3:0] count;
output reg [7:0] REGA;
output reg [7:0] REGB;
output reg [7:0] REGC;
output reg [7:0] REGD;
initial
begin
count <= 4'b0001;
REGA <= 8'b0;
REGB <= 8'b0;
REGC <= 8'b0;
REGD <= 8'b0;
valid_fifo <= 1'b0;
end
always #(posedge valid1)
begin
if(~rstn)
begin
count = 4'b0001;
REGA = 0;
REGB = 0;
REGC = 0;
REGD = 0;
end
else if(valid1 == 1'b1)
begin
case (count)
4'b0001: REGA = data_8;
4'b0010: REGB = data_8;
4'b0100: REGC = data_8;
4'b1000: REGD = data_8;
endcase
valid_fifo = 1'b0;
end
if(count == 4'b1000)
begin
data_32 = {REGD,REGC,REGB,REGA};
valid_fifo = 1'b1;
count = 4'b0001;
end
else
begin
count = count << 1;
end
end
endmodule
The module where I am instantiating it is called altogether.
Here is the code :
module altogether (
input wire BUTTON_AT,
input wire CLK_AT,
input wire RSTN_AT,
output wire MEM_FULL_AT,
output wire EMPTY_AT,
inout wire VALID_IN_AT,
inout wire [7:0] DATA_8_AT,
inout wire VALID1_AT,
inout wire [31:0] DATA_32_AT,
inout wire STOP_AT,
inout wire VALID_FIFO_AT,
inout wire [31:0] DATA_AT,
inout wire WR_AT,
inout wire [6:0] ADDR_AT,
output wire [7:0] REG_A_AT,
output wire [7:0] REG_B_AT,
output wire [7:0] REG_C_AT,
output wire [7:0] REG_D_AT,
output wire [3:0] COUNT_AT
);
shiftReg shift_register (
.data_8(DATA_8_AT),
.clk(CLK_AT),
.valid1(VALID_1_AT),
.rstn(RSTN_AT),
.data_32(DATA_32_AT),
.valid_fifo(VALID_FIFO_AT),
.REGA(REG_A_AT),
.REGB(REG_B_AT),
.REGC(REG_C_AT),
.REGD(REG_D_AT),
.count(COUNT_AT)
);
For some reason, the valid == 1'b1 condition is not executed when I put the shift register along with everything else. I have really run out of ideas, hope someone manages to look at it and give me an insight.
Somewhere during synthesis you probably got warning that you're using VALID_1_AT signal, which has no driver. That's because in altogether module declaration you define VALID1_AT signal (notice _ missing in signal name). That's why valid1 in your shift register is not driven at all.
You should change:
.valid1(VALID_1_AT)
into:
.valid1(VALID1_AT)
to make it works.

How I can find maximum number in verilog array

So, I have a reg[7:0] corr_Output[0:63]; which is filled with values in my module. How I can find maximum number in this array at one CLK cycle?
I wrote a 8 bit comparator:
module Comparator2D(
input [7:0] X1,
input [7:0] indexX1,
input [7:0] X2,
input [7:0] indexX2,
output [7:0] Y,
output [7:0] indexY
);
always begin
if (X1 > X2) begin
Y = X1;
indexY = indexX1;
end
else begin
Y = X2;
indexY = indexX2;
end
end
endmodule
But I dont know how I should instantiate this module in my top design? I think I should use "for loop", or even write another module which will concatenate my Comparator2D module in pyramid form, but as I found I cant pass whole array to input port of module, so Im a little stuck..
You can do it by using for/generate, like in this code sample, in which I can compare 8 bytes at a time.
The key point is that I cannot pass a memory as input (an array of registers), but I can pass an array of bits that hold the current values from memory.
// This is just your compare module.
module C2D (
input wire [7:0] X1,
input wire [7:0] indexX1,
input wire [7:0] X2,
input wire [7:0] indexX2,
output reg [7:0] Y,
output reg [7:0] indexY
);
always #* begin
if (X1 > X2) begin
Y = X1;
indexY = indexX1;
end
else begin
Y = X2;
indexY = indexX2;
end
end
endmodule
// Compare 8 bytes at a time
module greatest8bytes (
input wire [63:0] array, // 8 byte array
output wire [7:0] indexG,
output wire [7:0] valueG
);
wire [7:0] value_l1[0:3];
wire [7:0] index_l1[0:3];
genvar i;
generate
for (i=0;i<8;i=i+2) begin :gen_comps_l1
C2D cl1 (array[i*8+7:i*8],
i,
array[(i+1)*8+7:(i+1)*8],
(i+1),
value_l1[i/2],
index_l1[i/2]
);
end
endgenerate
wire [7:0] value_l2[0:1];
wire [7:0] index_l2[0:1];
generate
for (i=0;i<4;i=i+2) begin :gen_comps_l2
C2D cl2 (value_l1[i],
index_l1[i],
value_l1[i+1],
index_l1[i+1],
value_l2[i/2],
index_l2[i/2]
);
end
endgenerate
wire [7:0] value_l3[0:0];
wire [7:0] index_l3[0:0];
generate
for (i=0;i<2;i=i+2) begin :gen_comps_l3
C2D cl3 (value_l2[i],
index_l2[i],
value_l2[i+1],
index_l2[i+1],
value_l3[i/2],
index_l3[i/2]
);
end
endgenerate
assign indexG = index_l3[0];
assign valueG = value_l3[0];
endmodule
The greatest8bytes module is synthesized the way you expect: as a pyramid-like arrangement of comparators:
To connect an array of regs (a memory) to the input of this module, create a wire of the desired number of bits (64 in this example) and concatenate all elements of memory, like in this example module:
module findgreatest (
input wire clk,
input wire [2:0] addr,
input wire [7:0] data,
input wire we,
output wire [2:0] indexG,
output wire [7:0] valueG
);
reg [7:0] memory[0:7]; // 8 bytes
// To load data from the outside so the synthesizer won't throw away memory
always #(posedge clk) begin
if (we)
memory[addr] <= data;
end
wire [63:0] array = {memory[7],memory[6],memory[5],memory[4],
memory[3],memory[2],memory[1],memory[0]};
greatest8bytes compar (array, indexG, valueG);
endmodule
Not sure if this is synthesizable, but it is good to know that SystemVerilog has built in min and max functions:
module maximum ();
reg[7:0] corr_Output[0:63] = '{0:8'd112, 2:8'd250, 3:8'd37, 4:8'd15, default:8'd25};
reg[7:0] max_i[$];
reg[7:0] min_i[$];
initial begin
max_i = corr_Output.max;
min_i = corr_Output.min;
$display ("max=%d, min=%d", max_i[0], min_i[0]);
end
endmodule
Output:
# max=250, min= 15
Alternatively, it is probably shorter to just use this classic and synthesizable for-loop of comparisons:
always_comb begin
max = corr_Output[0];
for (c = 0; c <= 63; c++)
begin
if (corr_Output[c] > max)
begin
max = array[c];
index = c;
end
end

Verilog: Reading 1 bit input and Writing it to 288 bit reg

In verilog, I have a module name(input data,..., output...);
Data is only a single bit input and I need it to be displayed to reg [288:0] data_tmp; to compare the bits. How do I transfer data(input) to the reg?
I tried to handle it like an array in C using a for loop like so:
for(i=0; i<288; i=i+1) begin
data_tmp[i]=data;
end
But it doesn't appear to take any of the values from data or it is overwriting them.
Actual Code:
module inspector (
input rst_n, data, clk,
output total_cnt, skype_cnt, ftp_cnt, https_cnt, telnet_cnt, ssh_cnt, snmp_cnt, smtp_cnt,
nntp_cnt, telnet_session, skype_session, ssh_session
);
output [31:0] total_cnt;
output [7:0] skype_cnt;
output [7:0] ftp_cnt;
output [7:0] https_cnt;
output [7:0] telnet_cnt;
output [7:0] ssh_cnt;
output [7:0] snmp_cnt;
output [7:0] smtp_cnt;
output [7:0] nntp_cnt;
output [7:0] telnet_session;
output [7:0] skype_session;
output [7:0] ssh_session;
localparam INIT = 0;
localparam DATA = 1;
localparam PORT = 2;
localparam TOTAL = 3;
reg [287:0] data_tmp;
reg [3:0] Start_sequence = 32'hA5A5A5A5;
reg [1:0] state;
integer i;
always #(posedge clk)
if (rst_n) begin
total_cnt_tmp = 8'h00;
....
ssh_session_tmp = 8'h00;
end else begin
case (state)
INIT : begin
for(i=0; i<288; i=i+1) begin
data_tmp[i]=data;
end
if (data_tmp[31:0] == Start_sequence) begin
state <= DATA;
end else begin
state <= INIT;
end
end
.....
The for-loop is replicating the data; ie if data is 1 you get 288 ones, if data is 0 you get 288 zeros. What you want what is a shifter. data_tmp shift the bits to the left or right depending on the order of the bit stream.
data_tmp<={data_tmp[286:0],data}; // shift and fill left
or
data_tmp<={data,data_tmp[287:1]}; // shift and fill right
Also, remember to assign flops with non-blocking (<=). Blocking (=) for assigning combinational logic.

Resources