Behavioral verilog bcd up down counter with enable and reset - counter

I recently need to make a BCD up down counter with enable and reset. I have three always blocks but i dont know how to connect them together.
I have my code from code segments given by my teacher.
I wrote a structural verilog doing the same function before and I have no idea how to convert it to a behavioral type.
Here is my code:
module BCDcountmod(Clock, Clear, E, segment_a, segment_b, segment_c,
segment_d, segment_e, segment_f, segment_g, updown);
input Clock, Clear, E, updown;
output segment_a, segment_b, segment_c, segment_d, segment_e, segment_f, segment_g;
reg [6:0] segment_data;
reg [3:0] BCD1, BCD0;
always #(posedge Clock)
begin
if (Clear)
begin
BCD1 <= 0;
BCD0 <= 0;
end
else if (E)
if (updown)
if (BCD0 == 4′b1001)
begin
BCD0 <= 0;
if (BCD1 == 4′b0101)
BCD1 <= 0;
else
BCD1 <= BCD1 + 1;
end
else
BCD0 <= BCD0 + 1;
end
else
if (BCD0 == 4'b0000)
begin
BCD0 <= 4'b1001;
if (BCD1 == 4'b0000)
BCD1 <= 4'b0101;
else
BCD1 <= BCD1 - 1;
end
else
BCD0 <= BCD0 - 1;
end
always #(BCD0)
case (BCD0)
4'b0000: segment_data = 7'b1111110;
4'b0001: segment_data = 7'b0110000;
4'b0010: segment_data = 7'b1101101;
4'b0011: segment_data = 7'b1111001;
4'b0100: segment_data = 7'b0110011;
4'b0101: segment_data = 7'b1011011;
4'b0110: segment_data = 7'b1011111;
4'b0111: segment_data = 7'b1110000;
4'b1000: segment_data = 7'b1111111;
4'b1001: segment_data = 7'b1111011;
endcase
wire segment_a = ~segment_data[6];
wire segment_b = ~segment_data[5];
wire segment_c = ~segment_data[4];
wire segment_d = ~segment_data[3];
wire segment_e = ~segment_data[2];
wire segment_f = ~segment_data[1];
wire segment_g = ~segment_data[0];
always #(BCD1)
case (BCD1)
4'b0000: segment_data = 7'b1111110;
4'b0001: segment_data = 7'b0110000;
4'b0010: segment_data = 7'b1101101;
4'b0011: segment_data = 7'b1111001;
4'b0100: segment_data = 7'b0110011;
4'b0101: segment_data = 7'b1011011;
endcase
wire segment_a = ~segment_data[6];
wire segment_b = ~segment_data[5];
wire segment_c = ~segment_data[4];
wire segment_d = ~segment_data[3];
wire segment_e = ~segment_data[2];
wire segment_f = ~segment_data[1];
wire segment_g = ~segment_data[0];
endmodule

With the current setup both digits are being driven to the same 7-segment display. To make matters worse, segment_data has competing drivers. For code reuse, create a new module for bcd to 7-segment conversion. For example:
module segment7dec (output reg [6:0] display, input [3:0] bcd);
always #* begin
case(bcd)
4'b0000: display = 7'b1111110;
4'b0001: display = 7'b0110000;
4'b0010: display = 7'b1101101;
4'b0011: display = 7'b1111001;
4'b0100: display = 7'b0110011;
4'b0101: display = 7'b1011011;
4'b0110: display = 7'b1011111;
4'b0111: display = 7'b1110000;
4'b1000: display = 7'b1111111;
4'b1001: display = 7'b1111011;
default: display = 7'b0000000; //IMPORTANT, otherwise latches are inferred
endcase
display = ~display; // invert
end
endmodule
Now connect the new module into BCDcountmod. Remember to remove the old segment_* code.
module BCDcountmod(
input Clock, Clear, E, updown,
output [6:0] display1, display0 );
reg [3:0] BCD1, BCD0;
always #(posedge Clock) begin
/* Your logic for BCD1,BCD0
*
*/
end
segment7dec disp1( .display(display1), .bcd(BCD1) );
segment7dec disp0( .display(display0), .bcd(BCD0) );
endmodule
Example : http://www.edaplayground.com/s/6/398

Related

SystemVerilog X propagation issue

I'm having an issue with my SV code. I'm attempting to simulate a carry look ahead adder. However, when I look at my timing results
they show result has having an x propagated, as well as SUM.
Here is my SystemVerilog code
module fulladder (input logic i_bit1, i_bit2, i_carry,
output logic o_sum, o_carry);
assign o_sum = i_bit1 ^ i_bit2 ^ i_carry;
assign o_carry = (i_bit1 & i_bit2) | (i_carry & (i_bit1 ^ i_bit2));
endmodule
module carry_lookahead_adder
#(parameter WIDTH)
(input logic [WIDTH-1:0] i_add1,
input logic [WIDTH-1:0] i_add2,
output logic [WIDTH:0] o_result
);
logic [WIDTH:0] w_C;
logic [WIDTH-1:0] w_G, w_P, w_SUM;
//Generate full adders
genvar i;
generate for (i= 1; i<WIDTH; i++)
begin : f_loop
fulladder fi (
.i_bit1(i_add1[i]),
.i_bit2(i_add2[i]),
.i_carry(w_C[i]),
.o_sum(w_SUM[i]),
.o_carry()
);
end
endgenerate
genvar jj;
generate
for (jj=0; jj<WIDTH; jj++)
begin
assign w_G[jj] = i_add1[jj] & i_add2[jj];
assign w_P[jj] = i_add1[jj] | i_add2[jj];
assign w_C[jj+1] = w_G[jj] | (w_P[jj] & w_C[jj]);
end
endgenerate
assign w_C[0] = 1'b0; //No carry input
assign o_result = {w_C[WIDTH], w_SUM};
endmodule
and the testbench
module carry_lookahead_adder_tb (w_RESULT);
parameter WIDTH = 32;
logic [WIDTH-1:0] r_ADD_1 = 0;
logic [WIDTH-1:0] r_ADD_2 = 0;
output logic [WIDTH:0] w_RESULT;
carry_lookahead_adder #(.WIDTH(WIDTH)) carry_lookahead_inst
(
.i_add1(r_ADD_1),
.i_add2(r_ADD_2),
.o_result(w_RESULT)
);
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
#10;
r_ADD_1 = 32'b00000000000000000000000000000000;
r_ADD_2 = 32'b00000000000000000000000000000001;
#10;
r_ADD_1 = 32'b00000000000000000000000000000010;
r_ADD_2 = 32'b00000000000000000000000000000010;
#10;
r_ADD_1 = 32'b00000000000000000000000000000101;
r_ADD_2 = 32'b00000000000000000000000000000110;
#10;
r_ADD_1 = 32'b00000000100000000000000000000101;
r_ADD_2 = 32'b00000000100000000000000000000110;
#10;
r_ADD_1 = 32'b11111111111111111111111111111111;
r_ADD_2 = 32'b11111111111111111111111111111111;
#10;
r_ADD_1 = 32'b00000000000000000000000000000000;
r_ADD_2 = 32'b00000000000000000000000000000001;
#10;
end
endmodule // carry_lookahead_adder_tb
Can anyone clue me into what may be causing this x? Sorry to post my full code; I'm just lost as to where the problem may be coming from.
Bit [0] of w_SUM is unknown because you are not driving it. Change the generate for loop so that the count starts from 0, not 1. Change:
generate for (i= 1; i<WIDTH; i++)
to:
generate for (i= 0; i<WIDTH; i++)
After this change, the x goes away.
The problem was that the for loop was not generating the right number of fulladder instances: you need 32, but you only got 31. There was no fulladder instance for you to connect w_SUM[0], i_add1[0], etc., to.

verilog with out control variables cnt

module count(clk,rst,cnt);
want to wrire the verilog code which counts upto 7 and then down to
0 and repeats forever as follows. 0,1,2,3,4,5,6,7,6,5,4,4,3,2,1
endmodule
Blockquote
Repeat state 4 for two times while counting down:
module count(
input clk,
input rst,
output cnt
);
reg [2:0] counter;
assign cnt = counter;
// Count up if flag is 1'b0, count down if flag is 1'b1
wire flag;
assign flag = (counter == 3'b1) ? 1'b1 : (counter == 3'b0) ? 1'b0;
// Repeat counter once if special_flag is 2'b01
reg [1:0] special_flag;
always #(posedge clk)
begin
if (flag == 1'b0)
begin
counter = counter + 1;
end
else if (counter == 3'b100 && special_flag == 2'b01)
begin
// Do not decrease counter, reset special_flag back to 2'b0
special_flag = 2'b0;
end else
begin
counter = counter - 1;
end
// Set special_flag to be 2'b01 when counter is 3'b1
if (counter == 3'b1)
begin
special_flag = 2'b01;
end
end
endmodule
module count(
input clk,
input rst,
output cnt
);
reg [2:0] counter;
assign cnt = counter;
// Count up if flag is 1'b0, count down if flag is 1'b1
wire flag;
assign flag = (counter == 3'b1) ? 1'b1 : (counter == 3'b0) ? 1'b0;
always #(posedge clk)
begin
if (flag == 1'b0)
begin
counter = counter + 1;
end
if (flag == 1'b1)
begin
counter = counter - 1;
end
end
endmodule

System Verilog Generate - Unable to access local busses in previous loops using $size

enter image description here
I am trying to implement a OR tree using specific cell type CKOR2 in stages.
The stage is in a generate loop. I need to access the previous loops output bus width in the current loop to determine the width and define the output bus of the current stage.
I get errors on the line using $size
module test ( A, o );
parameter WIDTH = 9 ;
input [WIDTH-1:0] A;
output o;
localparam NUM_OR_STAGES = $clog2(WIDTH) ;
genvar i;
for (i=0; i < NUM_OR_STAGES; i=i+1) begin: OR
localparam j=i-1;
if ( i == 0 ) begin
localparam width = WIDTH;
wire [WIDTH-1:0] stgout;
assign stgout = A;
end
else begin
localparam width = $size( OR[i-1].stgout ) ;
localparam width_div2 = width/2;
localparam offset = ( width % 2);
wire [width_div2-1:0] stgo;
wire [width_div2+offset-1:0] stgout;
CKOR2 u_ckor[width_div2-1:0] ( .o(stgo), .i0(OR[i-1].stgout[width-1:width-width_div2]), .i1(OR[i-1].stgout[width-width_div2-1:width-2*width_div2]));
if ( offset )
assign stgout = { stgo,OR[i-1].stgout[0] };
else
assign stgout = stgo;
end
end
assign o = OR[NUM_OR_STAGES -1].stgout;
endmodule
Your problem is stgout[0] is declared inside an unnamed begin/end block, and you can't access it from outside the block. This is also a problem for the CKOR2 port connections. Naming the blocks would not solve your problem because you would have to switch between referencing the i==0 branch when i is 1, and the other branch when i!=1. Better to move the declarations outside the if/else branches. I didn't test the math, but this should get you close:
module test ( A, o );
parameter WIDTH = 9 ;
input [WIDTH-1:0] A;
output o;
localparam NUM_OR_STAGES = $clog2(WIDTH) ;
genvar i;
for (i=0; i < NUM_OR_STAGES; i=i+1) begin: OR
localparam width = WIDTH*2/(i+1);
localparam width_div2 = width/2;
localparam offset = ( width % 2);
wire [width_div2+offset-1:0] stgout;
if ( i == 0 ) begin
assign stgout = A;
end else begin
wire [width_div2-1:0] stgo;
CKOR2 u_ckor[width_div2-1:0] ( .o(stgo), .i0(OR[i-1].stgout[width-1:width-width_div2]), .i1(OR[i-1].stgout[width-width_div2-1:width-2*width_div2]));
if ( offset )
assign stgout = { stgo,OR[i-1].stgout[0] };
else
assign stgout = stgo;
end
end
assign o = OR[NUM_OR_STAGES -1].stgout;
endmodule

State machine transitions to impossible state on Signal Tap

I am trying to output one bit at a time via SPI from a know 2D array.
logic [7:0] fpga_status_queue [0:17],
My state machine is for some reason going to a weird state.
18'h
Here is my code:
module FPGA_STATUS_READ (
input clk,
input sclk,
input cs, // Clock Enable
input rst_n, // Asynchronous reset active low
input fpgastatus_command,
input logic [3:0] group_control,
input logic [7:0] loopback,
output logic [7:0] fpga_status_queue [0:17],
output logic dout
);
// `include "../../config_files/rtl_config.svh"
assign fpga_status_queue[ 0] = 8'h1;//{group_control};
assign fpga_status_queue[ 1] = 8'h1;//{loopback};
assign fpga_status_queue[ 2] = 8'h1;//{synth_version[0]};
assign fpga_status_queue[ 3] = 8'h1;//{synth_version[1]};
assign fpga_status_queue[ 4] = 8'h1;//{synth_version[2]};
assign fpga_status_queue[ 5] = 8'h1;//{grid_version[0]};
assign fpga_status_queue[ 6] = 8'h1;//{grid_version[1]};
assign fpga_status_queue[ 7] = 8'h1;//{grid_version[2]};
assign fpga_status_queue[ 8] = 8'h1;//{pa_version[0]};
assign fpga_status_queue[ 9] = 8'h1;//{pa_version[1]};
assign fpga_status_queue[10] = 8'h1;//{pa_version[2]};
assign fpga_status_queue[11] = 8'h1;//{hdl_version[0]};
assign fpga_status_queue[12] = 8'h1;//{hdl_version[1]};
assign fpga_status_queue[13] = 8'h1;//{hdl_version[2]};
assign fpga_status_queue[14] = '1;
assign fpga_status_queue[15] = '1;
assign fpga_status_queue[16] = '0;
assign fpga_status_queue[17] = '0;
logic bit_run_counter;
logic bit_load_counter;
logic [4:0] bit_current_value;
logic bit_count_reached;
logic word_run_counter;
logic word_load_counter;
logic [4:0] word_current_value;
logic word_count_reached;
typedef enum logic [2:0] {IDLE, CS_WAIT, MISO_OUT, BIT_CHANGE, WORD_CHANGE} status_states;
status_states current_state, next_state;
always_ff #(posedge clk or negedge rst_n) begin : step_forward
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end : step_forward
always_comb begin : set_next_state
next_state = IDLE;
case (current_state)
IDLE : next_state = fpgastatus_command ? CS_WAIT : IDLE;
CS_WAIT : next_state = ~cs ? MISO_OUT : CS_WAIT;
MISO_OUT : begin//next_state = sclk ? bit_count_reached ? word_count_reached ? IDLE: WORD_CHANGE : BIT_CHANGE: MISO_OUT;
if (sclk && bit_count_reached && word_count_reached)
next_state = IDLE;
else if (sclk && bit_count_reached)
next_state = WORD_CHANGE;
else if (sclk)
next_state = BIT_CHANGE;
else
next_state = MISO_OUT;
end
BIT_CHANGE : next_state = MISO_OUT;
WORD_CHANGE: next_state = MISO_OUT;
default : next_state = IDLE;
endcase
end
always_comb begin : cntr_logic
bit_run_counter = '0;
bit_load_counter = '0;
word_run_counter = '0;
word_load_counter = '0;
dout = '0;
unique case (current_state)
IDLE :begin
bit_load_counter = '1;
word_load_counter = '1;
end
CS_WAIT :begin
bit_load_counter = '1;
word_load_counter = '1;
end
MISO_OUT :begin
dout = fpga_status_queue[word_current_value][bit_current_value];
end
BIT_CHANGE :begin
bit_run_counter = '1;
end
WORD_CHANGE:begin
word_run_counter = '1;
bit_load_counter = '1;
end
default : dout = '0;
endcase
end
up_down_counter #(
.ABSOLUTE_DATA_WIDTH(4)
) inst_bit_counter (
.clk (clk),
.run_counter (bit_run_counter),
.rst_n (rst_n),
.count_value (5'h7),
.load_counter (bit_load_counter),
.up_counter ('0),
.current_value (bit_current_value),
.count_reached (bit_count_reached)
);
up_down_counter #(
.ABSOLUTE_DATA_WIDTH(5)
) inst_word_counter (
.clk (clk),
.run_counter (word_run_counter),
.rst_n (rst_n),
.count_value (5'h11),
.load_counter (word_load_counter),
.up_counter ('0),
.current_value (word_current_value),
.count_reached (word_count_reached)
);
endmodule
It should go to WORD_CHANGE but both WORD_CHANGE and MISO_OUT for the next state for current state.
This is almost certainly a timing issue. I'm guessing that sclk is not synchronous to clk - probably it's connected directly to a device input pin.
The problem is this piece of code:
(...)
else if (sclk)
next_state = BIT_CHANGE;
else
next_state = MISO_OUT;
Whenever sclk transitions from zero to one, logic will raise the next_state bit corresponding to BIT_CHANGE, and in parallel lower the next_state bit corresponding to MISO_OUT. As this happens, there can be a brief moment where both bits are set or no bits are set, depending on which logic is faster. If you are unlucky and have a raising clk at this exact moment, you will get into the situation you are observing, where the state machine appears to be in two states at the same time.
The solution is to synchronize sclk, cs, and any other signals that determine the next state to clk. Such synchronization is typically done by simply sending the signals through two flip-flops.

PCI-E Altera transmit-change-receive trouble

help to solve the problem.
I have a board Altera db4kgh15. It has built-in support pci-e interface. I have a Linux kernel module, which is controlled by the fee. with the function below I scan the base registers dogs and try to write in the register data.
The board should adopt a 32-bit word and send it back by adding to it 2.
However, the output we get the same number. The project on the FPGA to the main circuit module attached ksis own design.
Screenshot scheme and code module is presented below.
What am I doing wrong?
static int scan_bars(struct pci_dev *dev) {
int i;
int end = 0x3f;
ulong j;
for (i = 0; i < ALTPCIE_BAR_NUM; i++) {
unsigned long bar_start = pci_resource_start(dev, i);
if (bar_start) {
unsigned long bar_end = pci_resource_end(dev, i);
unsigned long bar_flags = pci_resource_flags(dev, i);
printk(KERN_INFO "##pci_m.ko# BAR%d 0x%08lx-0x%08lx flags 0x%08lx\n",
i, bar_start, bar_end, bar_flags);
virt_bar0 = (ulong) bus_to_virt(bar_start);
bar0 = bar_start;
printk(KERN_INFO "##pci_m.ko# Virt bar0 ADDR = 0x%08lx\n", virt_bar0);
if(bar0 == virt_bar0) {
printk(KERN_INFO "##pci_m.ko# bars equals!");
}
outl_p(number, bar0);
printk(KERN_INFO "##pci_m.ko# (bus) outl_p 0x%08lx\n", number);
/*for(j = bar0; j <= bar0 + end + 5; j++) {
printk(KERN_INFO "##pci_m.ko# (bus) inb_p[0x%08lx + %d] 0x%08lx\n", bar0, j - bar0, inb_p(j));
}*/
for(j = bar0; j <= bar0 + end + 5; j += 4) {
printk(KERN_INFO "##pci_m.ko# (bus) inl_p[0x%08lx + %d] 0x%08lx\n", bar0, j - bar0, inl_p(j));
}
outl_p(number, virt_bar0);
printk(KERN_INFO "##pci_m.ko# (virtual) outl_p 0x%08lx\n", number);
/*for(j = virt_bar0; j <= virt_bar0 + end + 5; j++) {
printk(KERN_INFO "##pci_m.ko# (virtual) inb_p[0x%08lx + %d] 0x%08lx\n", virt_bar0, j - virt_bar0, inb_p(j));
}*/
for(j = virt_bar0; j <= virt_bar0 + end + 5; j += 4) {
printk(KERN_INFO "##pci_m.ko# (virtual) inb_p[0x%08lx + %d] 0x%08lx\n", virt_bar0, j - virt_bar0, inl_p(j));
}
} else {
printk(KERN_INFO "##pci_m.ko# Could not correct read BAR #%d\n", i);
break;
}
}
return 0;
}
// bvs_pci_server1bar.v
`timescale 1 ps / 1 ps
module bvs_pci_server1bar #(
parameter AUTO_CLOCK_SINK_CLOCK_RATE = "-1"
) (
input wire [31:0] serv_bar1_0_addr, // avalon_slave.address
input wire serv_bar1_0_read, // .read
output wire serv_bar1_0_waitreq, // .waitrequest
input wire serv_bar1_0_write, // .write
output wire [63:0] serv_bar1_0_readd, // .readdata
input wire [63:0] serv_bar1_0_writed, // .writedata
input wire [6:0] serv_bar1_0_burstcnt, // .burstcount
input wire [8:0] serv_bar1_0_byteen, // .byteenable
output wire serv_bar1_0_readdatavalid, // .readdatavalid
output wire [19:0] serv_txs_addr, // avalon_master.address
output wire [7:0] serv_txs_byteen, // .byteenable
input wire [63:0] serv_txs_readd, // .readdata
output wire serv_txs_read, // .read
output wire serv_txs_write, // .write
input wire serv_txs_readdatavalid, // .readdatavalid
input wire serv_txs_waitreq, // .waitrequest
output wire serv_txs_chipsel, // .chipselect
output wire [6:0] serv_txs_burstcnt, // .burstcount
output wire [63:0] serv_txs_writed, // .writedata
input wire serv_rst, // reset_sink.reset
input wire serv_clk, // clock_sink.clk
output wire serv_irq // interrupt_sender.irq
);
// TODO: Auto-generated HDL template
assign serv_bar1_0_waitreq = 1'b0;
assign serv_bar1_0_readd = 64'b0000000000000000000000000000000000000000000000000000000000000000;
assign serv_bar1_0_readdatavalid = 1'b0;
assign serv_txs_burstcnt = 7'b0000000;
//assign serv_txs_writed = 64'b0000000000000000000000000000000000000000000000000000000000000000;
assign serv_txs_addr = 20'b00000000000000000000;
assign serv_txs_chipsel = 1'b0;
assign serv_txs_write = 1'b0;
assign serv_txs_read = 1'b0;
assign serv_txs_byteen = 8'b00000000;
//assign serv_irq = 1'b0;
reg[63:0] _value = 64'b0000000000000000000000000000000000000000000000000000000000000000;
reg _irq = 1'b0;
reg _txs_writed = 64'b0000000000000000000000000000000000000000000000000000000000000000;
always #(posedge serv_clk)
begin
if(serv_bar1_0_readd != _value)
begin
_value <= serv_bar1_0_readd;
_txs_writed <= serv_bar1_0_readd | 64'b0100000000000000000000000000000000000000000000000000000000000010;
_irq <= 1'b1;
end
else
_irq <= 1'b0;
end
assign serv_value = _value;
assign serv_irq = _irq;
assign serv_txs_writed = _txs_writed;
endmodule
plx_pci_io_base = pci_resource_start(dev, 0);
iolength = pci_resource_len(dev, 0);
if (!request_mem_region(plx_pci_io_base, iolength, "PGDR IO Base")) {
DEBUG(KERN_ERR "request region #1\n");
return -EBUSY;
}
iobase = ioremap_nocache(plx_pci_io_base, iolength);
if (!iobase) {
DEBUG(KERN_ERR "ioremap #1\n");
ret_status = -ENOMEM;
goto cleanup1;
}
You can try the following:
Use writel and readl instead of outl_p and inl_p
Check if the BAR register into which you are writing/reading and the BAR register used by RTL are same
Use Signal Tap to check if the RD/WR reach you RTL logic