I am trying to read the input from the file, and it is not reading the file fully. If there are 100 entries, it will only read 99. Here is the file and code. Any help would be appreciated. How do I know it? It is basically the sum of hit_count and miss_count should be the total number of input in the file and that is what is missing by 1.
module cache_memory_direct_mapped(input clk,
input reset,
input [3:0]read_addr,
output reg hit,
output reg miss,
output reg [7:0]hit_count,
output reg [7:0]miss_count);
reg [1:0]c1[3:0];
initial
begin
hit_count =8'h00;
miss_count = 8'h00;
end
always #(posedge clk, posedge reset)
begin
if(reset)
begin
c1[0] <= 2'hx;
c1[1] <= 2'hx;
c1[2] <= 2'hx;
c1[3] <= 2'hx;
end
else
begin
if(read_addr[3:2] == c1[0] || read_addr[3:2] == c1[1] || read_addr[3:2] == c1[2] || read_addr[3:2]
== c1[3])
begin
hit <= 1;
hit_count <= hit_count + 1;
miss <= 0;
end
else
begin
hit <= 0;
miss <= 1;
miss_count <= miss_count + 1;
if(read_addr[1:0] == 2'b0 )
c1[0] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b1 )
c1[1] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b10 )
c1[2] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b11 )
c1[3] <= read_addr[3:2];
end
end
end
endmodule
module Tb_direct_mapped;
// Inputs
reg clk;
reg reset;
reg [3:0] read_addr;
// Outputs
wire hit;
wire miss;
wire [7:0]hit_count;
wire [7:0]miss_count;
integer data_file ; // file handler
integer scan_file ; // file handler
reg [4:0]captured_data;
// Instantiate the Unit Under Test (UUT)
cache_memory_direct_mapped uut (
.clk(clk),
.reset(reset),
.read_addr(read_addr),
.hit(hit),
.miss(miss),
.hit_count(hit_count),
.miss_count(miss_count)
);
initial begin
// Initialize Inputs
clk = 0;
reset = 0;
data_file = $fopen("data_file.txt", "r");
end
always
#10 clk= ~clk;
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
if (!$feof(data_file)) begin
read_addr <= captured_data;
//$strobe(hit_count);
end
else begin
//$display("The total hit counts are:");
$display(hit_count);
$display(miss_count);
$finish;
end
end
endmodule
And here is the file:
6
9
4
A
8
2
9
5
7
9
7
4
9
7
6
8
Check for EOF before you read each line of the file:
always #(posedge clk) begin
if (!$feof(data_file)) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
read_addr <= captured_data;
//$strobe(hit_count);
end
else begin
//$display("The total hit counts are:");
$display(hit_count);
$display(miss_count);
$finish;
end
end
Related
I am trying to create a four element direct mapped cache with four bit memory address. Program is running completely fine no compilation error but suddenly in output, I am getting 'x' just for the first statement. After that I don't see it anywhere else. Any help would be appreciated. Here is the code
module cache_memory_direct_mapped(input clk,
input reset,
input [3:0]read_addr,
output reg hit,
output reg miss,
output reg [7:0]hit_count,
output reg [7:0]miss_count);
reg [1:0]c1[3:0];
initial
begin
hit_count =8'h00;
miss_count = 8'h00;
end
always #(posedge clk, posedge reset)
begin
if(reset)
begin
c1[0] <= 2'hx;
c1[1] <= 2'hx;
c1[2] <= 2'hx;
c1[3] <= 2'hx;
end
else
begin
if(read_addr[3:2] == c1[0] || read_addr[3:2] == c1[1] || read_addr[3:2] == c1[2] || read_addr[3:2] == c1[3])
begin
hit <= 1;
hit_count <= hit_count + 1;
miss <= 0;
end
else
begin
hit <= 0;
miss <= 1;
miss_count <= miss_count + 1;
if(read_addr[1:0] == 2'b0 )
c1[0] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b1 )
c1[1] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b10 )
c1[2] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b11 )
c1[3] <= read_addr[3:2];
end
end
end
endmodule
module Tb_direct_mapped;
// Inputs
reg clk;
reg reset;
reg [3:0] read_addr;
// Outputs
wire hit;
wire miss;
wire [7:0]hit_count;
wire [7:0]miss_count;
integer data_file ; // file handler
integer scan_file ; // file handler
reg [4:0]captured_data;
// Instantiate the Unit Under Test (UUT)
cache_memory_direct_mapped uut (
.clk(clk),
.reset(reset),
.read_addr(read_addr),
.hit(hit),
.miss(miss),
.hit_count(hit_count),
.miss_count(miss_count)
);
initial begin
// Initialize Inputs
clk = 0;
reset = 0;
data_file = $fopen("data_file.txt", "r");
end
always
#10 clk= ~clk;
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
if (!$feof(data_file)) begin
read_addr <= captured_data;
$display(hit);
//$display(hit_count);
end
else
$finish;
end
endmodule
And here is the picture of the output
Change:
$display(hit);
to:
$strobe(hit);
This outputs:
0
0
1
1
0
1
From the IEEE Std 1800-2017, section 21.2.2 Strobed monitoring:
The system task $strobe provides the ability to display simulation
data at a selected time. That time is the end of the current
simulation time, when all the simulation events have occurred for that
simulation time, just before simulation time is advanced.
The problem is that your signal values are changing at the time you call $display at posedge clk.
Here are some additional debugging tips:
Use a waveform debugger.
Display the simulation time as well as values: $strobe($time, " ", hit);
I can see an issue inside the "cache_memory_direct_mapped".
Under the else inside always (copied and pasted below)
if(read_addr[1:0] == 2'b0 )
c1[0] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b1 )
c1[1] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b10 )
c1[2] <= read_addr[3:2];
else if(read_addr[1:0] == 2'b11 )
c1[3] <= read_addr[3:2];
under each if statement you only assign a value to one section of C1, the rest will not be updated and carries their initial 'X'values. Can you assign 0 to the rest in each is/else if?
What happens if none of the conditions are not satisfied, you may need to have else statement at the end as well.
I am trying to create a four element direct mapped cache with 4-bit memory address. After creating a cache, I am reading the values from the file to figure out hits or misses on cache. But, somehow, my program is not terminating. Can someone please help me with this? I expect the simulation to end when the program has read the file. Here is the code with the testbench.
module cache_memory_direct_mapped(input clk,
input reset,
input [3:0]read_addr,
output reg hit,
output reg miss);
reg [1:0]c1[3:0];
reg [7:0]hit_count =8'h00;
reg [7:0]miss_count = 8'h00;
always #(posedge clk, posedge reset)
begin
if(reset)
begin
c1[0] <= 2'hx;
c1[1] <= 2'hx;
c1[2] <= 2'hx;
c1[3] <= 2'hx;
end
else
begin
if(read_addr[3:2] == c1[0])
//if(read_addr[3:2] == c1[0] || read_addr[3:2] == c1[1] || read_addr[3:2] == c1[2] ||
//read_addr[3:2] == c1[3])
begin
hit <= 1;
hit_count <= hit_count + 1;
miss <= 0;
end
else
begin
hit <= 0;
miss <= 1;
miss_count <= miss_count + 1;
if(read_addr[1:0] == 0 )
c1[0] <= read_addr[3:2];
else if(read_addr[1:0] == 1 )
c1[1] <= read_addr[3:2];
else if(read_addr[1:0] == 2 )
c1[2] <= read_addr[3:2];
else if(read_addr[1:0] == 3 )
c1[3] <= read_addr[3:2];
end
end
end
endmodule
module Tb_direct_mapped;
// Inputs
reg clk;
reg reset;
reg [3:0] read_addr;
// Outputs
wire hit;
wire miss;
integer data_file ; // file handler
integer scan_file ; // file handler
reg [4:0]captured_data;
// Instantiate the Unit Under Test (UUT)
cache_memory_direct_mapped uut (
.clk(clk),
.reset(reset),
.read_addr(read_addr),
.hit(hit),
.miss(miss)
);
initial begin
// Initialize Inputs
clk = 0;
reset = 0;
data_file = $fopen("data_file.txt", "r");
end
always
#10 clk= ~clk;
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
if (!$feof(data_file)) begin
read_addr <= captured_data;
end
end
endmodule
The simulation does not terminate because you did not specify when it should end.
always
#10 clk= ~clk;
The code above instructs the simulator to add a new event every 10 time units. It continues to add new events indefinitely, which is why the simulation does not end. One common way to stop a simulation is to use the $finish system task:
initial #100 $finish;
You should change 100 to be something more meaningful to your testbench.
Or, if you want to end the simulation after the file is read:
always #(posedge clk) begin
scan_file = $fscanf(data_file, "%h\n", captured_data);
if (!$feof(data_file)) begin
read_addr <= captured_data;
end else begin
$finish;
end
end
Why does r_D <= 8'h40 execute before w_Rx_DV == 1'b1 according to below code and waveform? R_D should not be assigned any value until w_Rx_DV goes high.
Thank you for any comments
Joe
module main(
input i_Clock,
input i_Rx_Serial,
output o_PWM
);
reg r_Load ;
reg [7:0] r_D =0;
wire w_Rx_DV;
wire [7:0] w_RX_Byte;
reg [7:0] r_RX_Byte;
PWM PWM(
.i_Clock(i_Clock),
.i_Load(r_Load),
.i_D (r_D),
.o_PWM(o_PWM)
);
rx rx(
.i_Clock (i_Clock),
.i_Rx_Serial (i_Rx_Serial),
.o_Rx_DV (w_Rx_DV),
.o_Rx_Byte (w_RX_Byte)
);
always # (posedge i_Clock)
begin
r_Load <= 0;
if(w_Rx_DV == 1'b1) ;
begin
r_RX_Byte <= w_RX_Byte;
if(r_RX_Byte ==8'h0)
begin
r_D <= 0;
r_Load <= 1;
end
if(r_RX_Byte == 8'h3F)
begin
r_D <= 8'h40;
r_Load <= 1;
end
else
begin
r_Load <= 0;
end
end
end
endmodule
waveform
Why does r_D <= 8'h40 execute before w_Rx_DV == 1'b1
Because you have a semicolon after the if here:
if(w_Rx_DV == 1'b1) ;
// ^ End of if statement.
I have written a verilog code for a simple coffee vending machine with inputs
25ps,50ps,75ps and 1
as
"00","01","10" and "11"
respectively. Coffee cost is 1 rs. If more than 1rs is inserted, the balance will be returned. That balance will be
01, 10, 11
as
25ps, 50ps, 1rs
respectively. I simulate this without test bench. simulation takes double clock pulse for output.(when i put 25 ps 8 times or 8 clock pulses is required for getting output. expected clock pulse is 4). Why this is happens? and also i didn't get output when using the test bench.
please help me to correct the test bench and my programme. Is clock frequency divider is necessary while doing the programme in fpga board to see output? It is working as expected when i programmed into fpga board.Im using Xilinx vivado 2015.2 tool and zynq board.Please help me to solve these issues
//programme
module main(
input clk,
input rst,
input [1:0] money,
output coffee,
output [1:0] balance
);
reg coff;
reg [1:0] bal;
reg [2:0] pr_st;
reg [2:0] nx_st;
parameter [2:0] A=3'b000;
parameter [2:0] B=3'b001;
parameter [2:0] C=3'b010;
parameter [2:0] D=3'b011;
parameter [2:0] E=3'b100;
parameter [2:0] F=3'b101;
parameter [2:0] G=3'b110;
parameter [2:0] H=3'b111;
always # (posedge clk or posedge rst)
begin
if(rst)
pr_st <= A;
else
pr_st <= nx_st;
end
always #(posedge clk)
begin
case(pr_st)
A : if(money == 2'b00) // input money is 25ps
begin
nx_st <= B;
end
else if(money == 2'b01) // input money is 50ps
begin
nx_st <= C;
end
else if(money == 2'b10) // input money is 75ps
begin
nx_st <= D;
end
else if(money == 2'b11)
begin
nx_st <= E;
end
B : if(money == 2'b00)
begin
nx_st <= C;
end
else if(money == 2'b01)
begin
nx_st <= D;
end
else if(money == 2'b10)
begin
nx_st <= E;
end
else if(money == 2'b11)
begin
nx_st <= F;
end
C : if(money == 2'b00)
begin
nx_st <= D;
end
else if(money == 2'b01)
begin
nx_st <= E;
end
else if(money == 2'b10)
begin
nx_st <= F;
end
else if(money == 2'b11)
begin
nx_st <= G;
end
D : if(money == 2'b00)
begin
nx_st <= E;
end
else if(money == 2'b01)
begin
nx_st <= F;
end
else if(money == 2'b10)
begin
nx_st <= G;
end
else if(money == 2'b11)
begin
nx_st <= H;
end
E : nx_st <= A;
F : nx_st <= A;
G : nx_st <= A;
H : nx_st <= A;
default : nx_st <= A;
endcase
end
//output logic
always #( posedge clk or pr_st)
begin
case(pr_st)
A: begin
coff <= 1'b0;
bal <= 2'b00;
end
B: begin
coff <= 1'b0;
bal <= 2'b00;
end
C: begin
coff <= 1'b0;
bal <= 2'b00;
end
D: begin
coff <= 1'b0;
bal <= 2'b00;
end
E: begin
coff <= 1'b1;
bal<= 2'b00;
end
F: begin
coff <= 1'b1;
bal <= 2'b01;
end
G: begin
coff <= 1'b1;
bal <= 2'b10;
end
H: begin
coff <= 1'b1;
bal <= 2'b11;
end
default : begin
off <=1'b0;
bal <= 2'b00;
end
endcase
end
assign coffee = coff;
assign balance = bal;
endmodule
//test bench
module tb_main(
);
reg clk;
reg rst;
reg [1:0] money;
wire coffee;
wire [1:0] balance;
main dut( clk, rst, money, coffee, balance);
always
begin
#200 clock = ~clk;
end
initial
begin
rst = 1'b1;
#100 rst = 1'b0;
money = 2'b00; // putting 25ps four times to get coffee
#400 money = 2'b01; //putting 50ps two times to get coffee
#200 money = 2'b10;// putting 75ps two times to get coffee
#200 money = 2'b11;// putting 1 rs single time to g
#100 money = 2'b01; // putting 1st 25ps and 50ps i n second clock cycle
#100 money = 2'b10;
#200
$finish
end
endmodule
You need to initialize your clock signal to a known value in the testbench. You should speed up the clock because your money input changes faster than the clock:
initial clk = 0;
always begin
#10 clk = ~clk;
end
I'm trying to make BCD Counter using Verilog that will be connected to 7-segment decoder.After I synthesize it, the error occured like this:
Multi-source in Unit <BCDcountmod> on signal <BCD0<3>>; this signal is connected to multiple drivers.>**And more.....***Any solution?* (Here's my code below)
module BCDcountmod(
input Clock, Clear, up, down,
output [3:0] BCD1_1, BCD0_0 );
reg [3:0] BCD1, BCD0;
//reg [3:0] BCD1_1, BCD0_0;
always #(posedge Clock) begin
if (Clear) begin
BCD1 <= 0;
BCD0 <= 0;
end
end
always #(posedge up) begin
if (BCD0 == 4'b1001) begin
BCD0 <= 0;
if (BCD1 == 4'b1001)
BCD1 <= 0;
else
BCD1 <= BCD1 + 1;
end
else
BCD0 <= BCD0 + 1;
end
always #(posedge down) begin
if (BCD0 == 4'b0000) begin
BCD0 <= 4'b1001;
if (BCD1 == 4'b1001)
BCD1 <= 4'b1001;
else
BCD1 <= BCD1 - 1;
end
else
BCD0 <= BCD0 - 1;
end
assign BCD1_1 = BCD1;
assign BCD0_0 = BCD0;
endmodule
You cannot modify BCD from different always blocks. Any modification should be perfomed in only one always. Something like:
module BCDcountmod(
input Clock, Clear, up, down,
output [3:0] BCD1_1, BCD0_0 );
reg [3:0] BCD1, BCD0;
//reg [3:0] BCD1_1, BCD0_0;
assign BCD1_1 = BCD1;
assign BCD0_0 = BCD0;
always #(posedge Clock) begin
//---- IS IT CLEAR? --------------
if (Clear) begin
BCD1 <= 0;
BCD0 <= 0;
end
//---- IS IT UP? --------------
else if (up) then begin
if (BCD0 == 4'b1001) begin
BCD0 <= 0;
if (BCD1 == 4'b1001)
BCD1 <= 0;
else
BCD1 <= BCD1 + 1;
end
end
//---- IS IT DOWN? --------------
else if (down) begin
if (BCD0 == 4'b0000) begin
BCD0 <= 4'b1001;
if (BCD1 == 4'b1001)
BCD1 <= 4'b1001;
else
BCD1 <= BCD1 - 1;
end
else
BCD0 <= BCD0 - 1;
end
end
endmodule
Just to add to mcleod_ideafix's answer you have this block:
always #(posedge Clock) begin
if (Clear) begin
BCD1 <= 0;
BCD0 <= 0;
end
end
Which implies a synchronous clear, I am not sure if that is your intention as typically you would have an asynchronous clear for you flip-flops in ASIC design, or set initial state for FPGA.
For a flip-flop with an asynchronous active-high clear
always #(posedge clock or posedge clear) begin
if (clear) begin
BCD1 <= 'b0; //NB: defined widths
BCD0 <= 'b0;
end
else
// normal logic
end
end
It is more typical to use active-low resets:
always #(posedge clock or negedge clear_n) begin
if (~clear_n) begin
BCD1 <= 'b0; //NB: defined widths
BCD0 <= 'b0;
end
else
if (up == 1'b1) begin
// up logic
end
else if (down == 1'b1) begin
// down logic
end
else begin
// nothing to see here
end
end
end
Doing comparisons with == 1'b1 means you will get a width mismatch warning instead of weird behaviour if the LHS (left hand side) is wider than 1 bit.
I also noticed that you have:
output [3:0] BCD1_1, BCD0_0 );
reg [3:0] BCD1, BCD0;
assign BCD1_1 = BCD1;
assign BCD0_0 = BCD0;
You just needed to do the following to have reg's as outputs:
output reg [3:0] BCD1, BCD0
Although I find the following much clearer:
output reg [3:0] BCD1,
output reg [3:0] BCD0