Code:
TestBench.v:
// ============================================================
//
// Traffic light tester module.
//
// We clock the device as usual, supply reset, and eventually "push
// the walk button" to activate the traffic light.
//
// ============================================================
// `timescale 1 ns / 1 ns
module TestBench;
reg clk; // Clock into the FPGA
reg walk; // A button that causes the walk light to go on
reg reset; // The reset line to your design
wire green; // The green light on Dodge Street
wire yellow; // The yellow light on ...
wire red; // The red light on ...
wire go; // The walk light for the pedestrian
wire stop; // The "don't walk" light
// Here is your FPGA chip
Traffic yourChip( reset, clk, walk, green, yellow, red, go, stop );
// Provide clocking to the FPGA
always
begin
#10 clk = ~clk;
end
// Start up code.
initial
begin
clk = 0;
walk = 0;
reset = 1;
#100 reset = 0;
end
// Eventually we want to "push the walk button" which causes the
// traffic lights to cycle yellow, red, then back to green.
// Also, we want to stop the sim at some point too.
initial
begin
#1000 walk = 1;
#100 walk = 0;
#100000 $stop;
end
endmodule // QuasiTestBench
clockDivder.v:
module clockDivider(
input wire clock,
input wire reset,
output wire dividedClk
);
reg [127:0] counter;
always #(posedge clock or posedge reset)
begin
if(reset == 1)
counter <=0;
else
counter <= counter + 1;
end
assign dividedClk = counter[127];
endmodule
Traffic.v:
module Traffic( reset, clock, walk, green, yellow, red, walkLight, handLight);
input wire reset;
input wire clock;
input wire walk;
output reg green, yellow, red, walkLight, handLight;
reg[2:0] state;
reg[3:0] count;
//we want some kind of state machine here.
//let's define some states
parameter s0 = 0 //green
, s1=1 //yellow
, s2=2; //red
reg[3:0] timeButtonPushed;
//clockDivider myClock(clock, reset);
always #(posedge clock or posedge reset)
begin
if (reset == 1)
begin
state <= s0; //default to green light on reset.
handLight = 1;
green = 1;
timeButtonPushed = 0;
count <= 0;
end
else
case(state)
s0:
begin
if(walk == 1)
begin
//compute 10s timeout before switch to yellow
//requires us to capture some info about time button pushed
timeButtonPushed = count; //record time button was pushed
end
else
if(timeButtonPushed == (count - 10))
begin
state = s1; //We've reached countdown state set light to yellow.
green = 0;
yellow = 1;
end
count = count + 1;
end
s1:
begin
if(timeButtonPushed == (count - 15)) //We've reached timeout for yellow light.
begin
state = s2; //move to red state
handLight = 0;
walkLight = 1;
red = 1;
end
count = count + 1;
end
s2:
begin
if(timeButtonPushed == count - 45)
begin
state = s0; //move back to green state
red = 0;
walkLight = 0;
handLight = 1;
green = 0;
timeButtonPushed = 0;
end
count = count + 1;
end
default: state <= s0;
endcase
end
endmodule
I've tried to instantiate the clockDivider in the TestBench, and I've also tried to instantiate it in Traffic.v attempting to insert it in between the clock and the input clk wire in Traffic.v
Ideally I'd like a solution that shows me the correct way to wire the clockDivider properly, however if there are other ways--even if hack-ish to get it done I'd appreciate it.
I've also tried forgetting clockDivider.v entirely and replaced the clock code with this:
reg [127:0] counter;
always
begin
if(reset == 1)
counter <=0;
else if(counter == 126)
assign clk = ~clk;
else
counter <= counter + 1;
end
But that too appears to fail.
Firstly, in your sample instantiation, you aren't connencting any signal to the dividedClk output. As such, it's hard to see what you're trying to use it for. You're allowed to omit connections, but you need the delimiting commas. Try: clockDivider myClock(clock, reset,);
Secondly, generating a clock with logic is poor design - you'll have major issues with timing. Logic signals can't be properly loaded onto the clock tree network, so you can get a large clock skew as a result. Instead, use your counter as an enable signal to any "slower" registers and use the global clock, or make use of a PLL/DLL to generate a new (slower) clock signal.
As an example of the first:
reg enable;
reg [127:0] counter;
parameter NUMBEROFCYCLES = 100;
always #(posedge clk)
begin
if (reset) enable <= 0;
else if (counter == NUMBEROFCYCLES) enable <= 1;
else enable <= 0;
end
always #(posedge clk)
begin
if (reset) counter <= 0;
else if (counter == NUMBEROFCYCLES) counter <= 0;
else counter <= counter + 1;
end
always #(posedge clk)
begin
if (reset) <<reset some signals>>
else if (enable) <<change some signals>>
else <<signals <= signals>>
end
Related
Sorry if anything in here seems obvious but I am starting out in this new FPGA thing and I really enjoy it so far but this is driving me crazy.
Here is the Verilog code for a block that should in principle do the following to an 8 bit register:
00000001
00000010
00000100
.....
01000000
10000000
01000000
00100000
module bit_bouncer(clock, enable, bouncer_out);
//INPUTS PORTS
input clock;
input enable;
//OUTPUTS PORTS
output bouncer_out;
//INPUT DATA TYPE
wire clock;
wire enable;
//OUTPUT DATA TYPE
reg [7:0] bouncer_out = 8'b00000001;
//Register to store data
reg direction = 0;
//CODE STARTS HERE
always # (posedge clock) begin
if(enable) begin
bouncer_out = direction ? (bouncer_out >> 1) : (bouncer_out << 1);
direction <= (bouncer_out == 8'b00000001 || bouncer_out == 8'b10000000) ? ~direction : direction;
end
end
endmodule
This works perfectly in simulation but fails on the FPGA (DE10-Nano board, if interested).
I should also point out that this gets driven by a clock passed trough a PLL on the FPGA that is then
passed trough a divideByN block.
Here is the code for the divideByN block:
module clk_divn #(
parameter WIDTH = 20,
parameter N = 1000000)
(clk,reset, clk_out);
input clk;
input reset;
output clk_out;
reg [WIDTH-1:0] pos_count = {WIDTH{1'b0}};
reg [WIDTH-1:0] neg_count = {WIDTH{1'b0}};
wire [WIDTH-1:0] r_nxt = {WIDTH{1'b0}};
always #(posedge clk)
if (reset)
pos_count <=0;
else if (pos_count ==N-1) pos_count <= 0;
else pos_count<= pos_count +1;
always #(negedge clk)
if (reset)
neg_count <=0;
else if (neg_count ==N-1) neg_count <= 0;
else neg_count<= neg_count +1;
assign clk_out = ((pos_count > (N>>1)) | (neg_count > (N>>1)));
endmodule
The divideByN has also been tested in simulation and works fine.
I actually made a simulation in which the divideByN is connected to the "bouncer_block" if I can
call it like that and it also works.
Everything simulates but nothing works in real life....but isn't it always like that :P
I hope someone can help me figure this out because I really want to learn more about FPGA and use
them in future projects.
If you read all this you are awesome and I wish you an amazing day :)
Your bit bouncer is not operating synchronously to the system clock and neither does it have a reset condition, which is a recipe for trouble.
A better approach is to use a clock strobe and test for it on edges of the main system clock. Also, all inputs from tactile buttons should be synchronised to the system clock and debounced. Something like this:
Schematic
RTL
BitBouncer
module BitBouncer
(
input wire clock,
input wire reset,
input wire enable,
input wire clock_strobe,
output reg[7:0] bouncer_out
);
// Register to store data
reg direction = 0;
// CODE STARTS HERE
always #(posedge clock)
begin
if (reset)
begin
bouncer_out = 1;
direction = 0;
end
else if (enable && clock_strobe)
begin
bouncer_out = direction ? (bouncer_out >> 1) : (bouncer_out << 1);
direction <= (bouncer_out == 8'b00000001 || bouncer_out == 8'b10000000) ? ~direction : direction;
end
end
endmodule
ClockStrobe
module ClockStrobe
#(
parameter MAX_COUNT = 50000000
)
(
input wire clock,
input wire reset,
output reg clock_strobe
);
reg [$clog2(MAX_COUNT) - 1: 0] counter;
always #(posedge clock)
begin
if (reset)
begin
counter <= 0;
end
else
begin
counter <= counter + 1;
if (counter == MAX_COUNT)
begin
clock_strobe <= 1;
counter <= 0;
end
else
begin
clock_strobe <= 0;
end
end
end
endmodule
Sync
module Sync
(
input wire clock,
input wire in,
output reg out
);
reg [2:0] sync_buffer;
initial
begin
out = 0;
sync_buffer = 3'd0;
end
always #*
begin
out <= sync_buffer[2];
end
always #(posedge clock)
begin
sync_buffer[0] <= in;
sync_buffer[2:1] <= sync_buffer[1:0];
end
endmodule
Debounce
module Debounce
#(
parameter MAX_COUNT = 2500000
)
(
input wire clock,
input wire in,
output reg out
);
reg previous_in;
reg [$clog2(MAX_COUNT) - 1:0] counter;
initial begin
previous_in = 0;
counter = 0;
out = 0;
end
always #(posedge clock)
begin
counter <= counter + 1;
if (counter == MAX_COUNT)
begin
out <= previous_in;
counter <= 0;
end
else if (in != previous_in)
begin
counter <= 0;
end
previous_in <= in;
end
endmodule
I have tried to add a reset with no success but I have made my own divideByN and kept the reset Charles suggested and now it's working flawlessly. I think the code for the divideByN I took online might be unable to synthesize properly. Here is my new code for the divideByN:
module my_div_n #(parameter N = 1_000_000, parameter WIDTH = 20) (clock_in,
clock_out);
input wire clock_in;
output reg clock_out;
reg[WIDTH-2:0] counter; //WIDTH-2 because the last bit is taken care of by the fact that we flip the output (it acts as the last bit)
always # (posedge clock_in) begin
counter <= counter + 19'b1;
if(counter == N>>1) begin
counter <= 0;
clock_out <= !clock_out;
end
end
endmodule
And the code for my bit_bouncer:
module bit_bouncer(clock, enable, reset, bouncer_out);
//INPUTS PORTS
input clock;
input enable;
input reset;
//OUTPUTS PORTS
output [7:0] bouncer_out;
//INPUT DATA TYPE
wire clock;
wire enable;
wire reset;
//OUTPUT DATA TYPE
reg [7:0] bouncer_out;
//Register to store data
reg direction;
//CODE STARTS HERE
always # (posedge clock) begin
if(reset) begin
bouncer_out <= 8'b00000001;
direction <= 0;
end
else if(enable) begin
bouncer_out = direction ? (bouncer_out >> 1) : (bouncer_out << 1);
direction <= (bouncer_out == 8'b00000001 || bouncer_out == 8'b10000000) ? ~direction : direction;
end
end
endmodule
Here how everything is wired:
I would still like to know the purpose of the clock strobe because you make it seem as if I should probably know this if I want to understand my circuit better and all about synchronicity.
I wanted to design a FIFO having a certain depth and width. The Verilog code of the FIFO is written in Vivado 2017.4. The code is able to to read the input data, but it is only showing XX as the output. The design sources and test bench of the FIFO is given below. Help me to find the problem.
module fifo #(parameter WIDTH=8, parameter DEPTH=8) (
input wire [WIDTH-1:0] data_in,
output reg [WIDTH-1:0] data_out,
output reg data_valid,
input wire reset,
input wire clk
);
function integer clog2(input reg [32-1:0] value);
begin
value = value-1;
for (clog2=0; value>0; clog2=clog2+1)
value = value>>1;
end
endfunction
reg [WIDTH-1:0] data [DEPTH-1:0];
reg [clog2(DEPTH)-1:0] write_pointer;
reg [clog2(DEPTH)-1:0] read_pointer;
always #(posedge clk) begin
if (reset == 1'b0) begin
write_pointer <= 0;
read_pointer <= 1;
data_valid <= 0;
end else begin
if (write_pointer == DEPTH-1) write_pointer <= 0;
else write_pointer <= write_pointer + 1;
if (read_pointer == DEPTH-1) read_pointer <= 0;
else read_pointer <= read_pointer + 1;
data[write_pointer] <= data_in;
data_out <= data[read_pointer];
end
if (read_pointer == 0) data_valid <= 1'b1;
end
endmodule
test bench
`timescale 1ns / 1ps
module fifo_tb;
parameter WIDTH = 16;
parameter DEPTH = 8;
reg reset;
reg clk;
reg [(WIDTH-1):0] data_in;
wire [(WIDTH-1):0] data_out;
wire data_valid;
fifo #(WIDTH,DEPTH) U0(data_in,data_out,data_valid,reset,clk);
initial begin
clk = 0;
reset = 1;
#1 reset = 0;
#1 reset = 1;
end
// Create clock
always
#5 clk = ~clk;
reg signed [15:0] rom_memory [4096-1:0];
integer i=0;
initial
begin
$readmemh("C:\\Users\\input_7_zz.txt",rom_memory);
end
always#(posedge clk )
begin
if(~reset)
begin
data_in <= 0;
end
else
begin
data_in <= rom_memory[i];
i <= i+ 1;
end
end
endmodule
In your test bench code the clock is changed every 5 ticks:
// Create clock
always
#5 clk = ~clk;
The reset in RTL uses posedge of this clock:
always #(posedge clk) begin
if (reset == 1'b0) begin
write_pointer <= 0;
read_pointer <= 1;
data_valid <= 0;
So, the reset action could happen only if the posedge clk could be detected during the reset period. In other words you have a synchronous reset.
Nevertheless, in your test bench code your reset lasts only a single tick:
initial begin
clk = 0;
reset = 1;
#1 reset = 0;
#1 reset = 1; // << one tick after the reset was asserted.
end
Potentially you have 2 possible solutions.
1) keep the synchronous reset, but make sure that the posedge of the clk could be detected during the reset. So, make it bigger than a clock cycle (or at least half clock cycle if you are sure when it comes). Something like 5 should work in your case. Make it 10 or more to be sure for arbitrary starting points.
initial begin
clk = 0;
reset = 1;
#1 reset = 0;
#5 reset = 1; // << 5 tick after the reset was asserted.
The reset above will last from time 1 to time 6. The first posegde will happen at time 5. So, it should be sufficient in your case.
2) you can use an asynchronous reset in RTL which will look as the following:
always #(posedge clk or reset) begin
if (reset == 1'b0) begin
write_pointer <= 0;
read_pointer <= 1;
data_valid <= 0;
In the above case the always block will be executed whenever 'reset' changes. However you have to be careful about the timing of other assignment there. They could happen when you deassert reset with some offset from the posedge clk.
I've got a simple project which requires me to write a code for RS232 receiver and sender, then put them together and, finally, test if it works properly. I've prepared code for both sender and receiver (and also connecting block - top). My problem is that I don't know how to connect them, so they could work with each other properly.
The main issue is that I can't "transfer" data from data_o to data_i because of the fact that one is reg and second - wire. I wouldn't like to use inout for these purposes. I can't figure out any possible modifications to make it work.
Another issue is putting some flags that could kind of follow idea like this: if receiving -> not sending, if sending -> not receiving.
Here's my code:
top.v
`timescale 1ns / 1ps
module top (
clk_i,
rst_i,
RXD_i,
data_i,
TXD_o,
data_o
);
input clk_i;
input rst_i;
input RXD_i;
output TXD_o;
//the problem is here, can't data_i <= data_o because output is reg
input [7:0] data_i;
output [7:0] data_o;
receiver r1(clk_i, RXD_i, data_o);
sender s1(clk_i, data_i, TXD_o);
endmodule
receiver.v
`timescale 1ns / 1ps
module receiver (
clk_i,
RXD_i,
data_o
);
//inputs and outputs
input clk_i;
input RXD_i;
output reg [7:0] data_o;
//counter values
parameter received_bit_period = 5208;
parameter half_received_bit_period = 2604;
//state definitions
parameter ready = 2'b00;
parameter start_bit = 2'b01;
parameter data_bits = 2'b10;
parameter stop_bit = 2'b11;
//operational regs
reg [12:0] counter = 0; //9765.625Hz
reg [7:0] received_data = 8'b00000000;
reg [3:0] data_bit_count = 0;
reg [1:0] state = ready;
//latching part
reg internal_RXD;
always #(posedge clk_i) //latch RXD_i value to internal_RXD
begin
internal_RXD = RXD_i;
end
always #(clk_i) //receiving process
begin
case (state)
ready :
begin
if (internal_RXD == 0)
begin
state <= start_bit;
counter <= counter + 1;
end
else
begin
state <= ready;
counter <= 0;
data_bit_count <= 0;
end
end
start_bit :
begin
if (counter == half_received_bit_period)
begin
if (internal_RXD == 0)
begin
state <= data_bits;
counter <= 0;
end
end
else
begin
state <= start_bit;
counter <= counter + 1;
end
end
data_bits :
begin
if (counter == received_bit_period)
begin
received_data[data_bit_count] <= internal_RXD;
data_bit_count <= data_bit_count + 1;
counter <= 0;
if (data_bit_count == 8)
state <= stop_bit;
end
else
counter <= counter + 1;
end
stop_bit:
begin
counter <= counter + 1;
if (counter == received_bit_period)
begin
state <= ready;
data_o <= received_data;
end
end
endcase
end
endmodule
sender.v
`timescale 1ns / 1ps
module sender (
clk_i,
data_i,
TXD_o
);
//inputs and outputs
input clk_i;
input [7:0] data_i;
output reg TXD_o;
//counter values
parameter received_bit_period = 5208;
parameter half_received_bit_period = 2604;
//state definitions
parameter ready = 1'b0;
parameter data_bits = 1'b1;
//operational regs
reg [12:0] counter = 0; //9765.625Hz
reg [9:0] framed_data = 0;
reg [3:0] data_bit_count = 0;
reg state = ready;
always #(posedge clk_i) //sending process
begin
case (state)
ready :
begin // flag needed?
state <= data_bits;
TXD_o <= 1;
framed_data[0] <= 1'b0;
framed_data[8:1] <= data_i;
framed_data[9] <= 1'b1;
counter <= 0;
end
data_bits :
begin
counter <= counter + 1;
if (data_bit_count == 10)
begin // flag needed?
state <= ready;
data_bit_count <= 0;
TXD_o <= 1;
end
else
begin
if (counter == received_bit_period)
begin
data_bit_count <= data_bit_count + 1;
end
TXD_o <= framed_data[data_bit_count];
end
end
endcase
end
endmodule
You don't!
In all CPU's and FPGA nowadays the read and write data path are separate buses. You will find that also with all CPU cores. Have a look at AXI or AHB bus protocols from ARM.
What is more worrying is the way you have implemented your functions. You would at least need some 'data valid' signal for the transmitter to know when there is valid data to transmit and for the receive when valid data has arrived.
Even that is not enough because for the TX the connecting logic would need to know when the data has been send and the next byte can go out.
You need to make a (preferably standard) CPU interface which talks to your UART. (For beginner I would not use AXI.)
As to your flags: they would come from within the CPU interface.
Last: a UART should be capable of transmitting and receiving at the same time.
EDIT: removed some redundancies, moved all assignments to non-blocking, inserted a reset mapped as one of the input buttons of my FPGA... but when I implement the code, it starts transmitting the same wrong character and gets stuck in a single state of my machine.
Post Synthesis and Post-Implementation simulations are identical,$time-wise
module UART (reset_button, sysclk_p, sysclk_n,TxD, Tx_busy, Tx_state_scope_external);
input reset_button, sysclk_p, sysclk_n;
output wire TxD, Tx_busy;
output wire [1:0]Tx_state_scope_external;
//internal communications signals
wire clk_internal;
//buffer unit control signals
wire [7:0]TxD_data_internal;
wire Tx_start_internal;
wire Tx_busy_internal;
wire reset_flag;
reset_buf RESET_BUFF (.reset_internal (reset_flag), .reset (reset_button));
differential_CK CK_GENERATION (.sysclk_p (sysclk_p), .sysclk_n(sysclk_n), .clk(clk_internal));
output_Dbuffer OB1 (.reset (reset_flag), .RTS_n (Tx_busy_internal), .clk(clk_internal), .TX_trigger (Tx_start_internal), .TX_data(TxD_data_internal));
async_transmitter TX1 (.reset (reset_flag), .clk (clk_internal), .TxD_data(TxD_data_internal), .Tx_start (Tx_start_internal), .TxD(TxD), .Tx_busy_flag(Tx_busy_internal), .Tx_state_scope(Tx_state_scope_external));
obuf_TX O_TX1( .Tx_busy(Tx_busy), .Tx_busy_flag(Tx_busy_internal));
endmodule
module reset_buf (
output reset_internal,
input reset
);
// IBUF: Single-ended Input Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
IBUF #(
.IBUF_LOW_PWR("TRUE"), // Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUF_inst (
.O(reset_internal), // Buffer output
.I(reset) // Buffer input (connect directly to top-level port)
);
// End of IBUF_inst instantiation
endmodule
module differential_CK(
input sysclk_p,
input sysclk_n,
output clk
);
// IBUFGDS: Differential Global Clock Input Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
IBUFGDS #(
.DIFF_TERM("FALSE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUFGDS_inst (
.O(clk), // Clock buffer output
.I(sysclk_p), // Diff_p clock buffer input (connect directly to top-level port)
.IB(sysclk_n) // Diff_n clock buffer input (connect directly to top-level port)
);
// End of IBUFGDS_inst instantiation
endmodule
module output_Dbuffer (
input reset,
input RTS_n, //TX_BUSY flag of the transmitter is my ready to send flag
input clk, //ck needed for the FSM
output wire TX_trigger, //TX_START flag of the transmitter now comes from THIS unit instead of Receiver
output wire [7:0]TX_data //byte for transmission
);
//internal variables
reg [7:0] mem [0:9]; //memory init, 10 * 8 bit locations
integer m, n, i, j, k ; //M = row [a.k.a. bytes], N = column [a.k.a. single bits]
reg TX_trigger_int;
reg [7:0] TX_data_int, TX_complete;
//reg sum256_ok;
reg [7:0]checksum_buff ;
//buffer FSM required variables
localparam //state enumeration declaration
BUF_IDLE = 3'b000,
BUF_START = 3'b001,
BUF_BYTES = 3'b010,
BUF_BUSY = 3'b011,
BUF_TX_CHECKSUM = 3'b100;
reg [2:0] buf_state; //2 bits for 4 states
//static assignments of OUTPUTS : Transmission Flag and Transmission Data (content)
assign TX_trigger = TX_trigger_int;
assign TX_data = TX_data_int;
//Block for transmitting [here I manage the TX_Data and TX_Trigger functionality]
always #(posedge clk)
begin
if (reset)
begin
buf_state <= BUF_IDLE;
TX_trigger_int <= 0;
TX_data_int <= 8'b00000000;
end
else case (buf_state)
BUF_IDLE:
begin
TX_trigger_int <= 0;
TX_data_int <= 8'b00000000;
m <=0;
n <=0;
i <=0;
j <=0;
mem[9] <= 8'b01010001; //81
mem[8] <= 8'b01000000; //64
mem[7] <= 8'b00110001; //49
mem[6] <= 8'b00100100; //36
mem[5] <= 8'b00011001; //25
mem[4] <= 8'b00010000; //16
mem[3] <= 8'b00001001; //9
mem[2] <= 8'b00000100; //4
mem[1] <= 8'b00000001; //1
mem[0] <= 8'b00000010;//2
checksum_buff <= 8'd31;
//check if the TX is not busy
if (RTS_n == 0) buf_state <= BUF_START;
end
BUF_START:
begin
TX_trigger_int <= 0;
if ((i == 0) || ( (j - i) > 1 )) buf_state <= BUF_BYTES;
else begin
$display ("BUFFER BUSY #time:", $time);
buf_state <= BUF_BUSY;
end
end
BUF_BYTES:
begin
//check if the TX is busy
if (RTS_n==0)
begin
// TX_trigger_int = 1; 21.09 MOVED THE TRIGGER INSIDE THE ELSE N LINE 498
if (j > 9)
begin
TX_trigger_int <= 0;
buf_state <= BUF_TX_CHECKSUM;
end
else begin
TX_data_int <= mem[j];
TX_trigger_int <= 1;
j <= j+1;
//TX_trigger_int =0;
buf_state <= BUF_START;
end
end
else buf_state <= BUF_BYTES;
end
BUF_BUSY:
begin
if (RTS_n == 0)
begin
$display ("BUFFER AVAILABLE AGAIN #time:", $time);
buf_state <= BUF_START;
end
end
BUF_TX_CHECKSUM:
begin
if (RTS_n==0) begin
TX_data_int <= checksum_buff;
// sum256_ok = 0;
TX_trigger_int <= 1;
buf_state <= BUF_IDLE;
end
end
//default: buf_state <= BUF_IDLE;
endcase
end
endmodule
module async_transmitter(
input clk,
input reset,
//differential clock pair
input [7:0] TxD_data,
input Tx_start, // it is ==TX_TRIGGER
output wire TxD, //bit being sent to the USB
output reg Tx_busy_flag,
output wire [1:0]Tx_state_scope
);
localparam //state enumeration declaration
TX_IDLE = 2'b00,
TX_START_BIT = 2'b01,
TX_BITS = 2'b10,
TX_STOP_BIT = 2'b11;
parameter ClkFrequencyTx = 200000000; // 200MHz
parameter BaudTx = 9600;
reg [1:0] Tx_state; //2 bits for 4 states
integer bit_counter; //bit counter variable
reg [7:0]TxD_data_int, TxD_int;
integer i; //vector index for output data
wire TXSTART_Trigger;
StartDetectionUnitTX SDU_TX (.clk(clk), .state (Tx_state), .signal_in (Tx_start), . trigger (TXSTART_Trigger));
wire BitTick;
BaudTickGen #(ClkFrequencyTx, BaudTx) as (.clk(clk), .trigger (TXSTART_Trigger), .tick(BitTick));
//BitTick is 16times the frequency generated during the RX portion
assign TxD = TxD_int;
always #(posedge clk) begin
if (reset)
begin
Tx_state <= TX_IDLE;
TxD_int <= 1;
Tx_busy_flag <=0;
end
else case (Tx_state)
TX_IDLE:
begin //reinitialization and check on the trigger condition
bit_counter <= 0;
TxD_data_int <= 8'b00000000;
i <= 0;
TxD_int <= 1; //idle state
Tx_busy_flag <= 0;
if (TXSTART_Trigger) begin
Tx_state <= TX_START_BIT;
TxD_data_int <= TxD_data;
Tx_busy_flag <= 1;
bit_counter <= 8;
end
end
TX_START_BIT:
begin
if (BitTick)
begin
TxD_int <= 0 ; //start bit is a ZERO logical value
Tx_state <= TX_BITS;
end
end
TX_BITS:
begin
if (BitTick)
begin
bit_counter <= bit_counter -1;
TxD_int <= TxD_data_int[i];
// $display ("ho trasmesso dalla UART un bit di valore %b al tempo: ", TxD, $time);
i <= i+1;
if (bit_counter < 1) Tx_state <= TX_STOP_BIT;
end
end
TX_STOP_BIT:
begin
if (BitTick) begin
TxD_int <= 1; //STOP BIT is a logical '1'
Tx_busy_flag <= 0;
Tx_state <= TX_IDLE;
end
end
// default: Tx_state <= TX_IDLE;
endcase
end
assign Tx_state_scope = Tx_state;
endmodule
module obuf_TX (
output Tx_busy,
input Tx_busy_flag
);
// OBUF: Single-ended Output Buffer
// 7 Series
// Xilinx HDL Libraries Guide, version 14.7
OBUF #(
.DRIVE(12), // Specify the output drive strength
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW") // Specify the output slew rate
) OBUF_inst (
.O(Tx_busy), // Buffer output (connect directly to top-level port)
.I(Tx_busy_flag) // Buffer input
);
// End of OBUF_inst instantiation
endmodule
module StartDetectionUnitTX ( //detects a rising edge of the start bit == TRANSMISSION START, during the IDLE state = 0000
input clk, [1:0]state,
input signal_in,
output trigger
);
reg signal_d;
always #(posedge clk)
begin
signal_d <= signal_in;
end
assign trigger = signal_in & (!signal_d) & (!state);
endmodule
module BaudTickGen (
input clk, trigger,
output tick //generates a tick at a specified baud rate *oversampling
);
parameter ClkFrequency = 200000000; //sysclk at 200Mhz
parameter Baud = 9600;
parameter Oversampling = 1;
//20832 almost= ClkFrequency / Baud, to make it an integer number
integer counter = (20833/Oversampling)-1; //-1 so counter can get to 0
reg out;
always #(posedge clk)
begin
if (trigger)
begin
counter <= (20833/Oversampling)-1; //-1 so counter can get to 0
out <= 1;
end
if (counter == 0)
begin
counter <= (20833/Oversampling)-1; //-1 so counter can get to 0
out <= 1;
end
else begin
counter <= counter-1;
out <= 0;
end
end
assign tick = out;
endmodule
My FPGA is a Virtex-7 VC707 and I'm using Vivado for my design flow.
Here I am attaching an image of my looping error.
error image
What have you done? Have you just simulated the code? Are you saying that it fails on the board, but the post-implementation sim is Ok?
A difference between pre- and post-implementation sim could point to a race condition. Get rid of all your blocking assignments, replace with NBAs (why did you use blocking assignments?)
Don't go to Chipscope - it's just a red flag that you don't know what you're doing
The code is a mess - simplify it. The Xilinx-specific stuff is irrelevant - get rid of it if you want anyone to look at it, fix comments (2-bit state?!), fix your statement about getting stuck in '10', etc
Have you run this through Vivado? Seriously? You have multiple drivers on various signals. Get rid of the initial block, use a reset. Initialise the RAM in a way which is understood by the tools. Even if Vivado is capable of initialising stuff using a separate initial block, don't do it
Get rid of statements like 'else Tx_state = TX_IDLE' in the TX_IDLE branch - they're redundant, and just add verbosity
Write something which fails stand-alone, and post it again.
I want to make a simple project on which I load 10 numbers in SDRAM of my Altera DE1-SOC ready to be taken as input for a Logic Unit I am creating,
the logic unit only does a simple arithmetic " Y =(X+1)*(X-1), X is the input and Y is the output ".It will pick the values (one by one) from the SDRAM, calculate and spit out the result in another SDRAM arrangement.
Then the SDRAM should store this data, I wish to take this data out of the DE1-SOC to a PC, for example.
Until now I've done this code, (in case is necessary to check):
module mem_prue1 (rst_n, clk, fin);
input clk, rst_n;
output fin;
wire [6:0] data_X;
reg [6:0] sec_A, sec_B, s_sec_A, s_sec_B;
reg [13:0] rslt_Y, s_rslt_Y;
reg save_sec_A, save_sec_B, save_rslt_Y, set_ram;
reg clear, enable, next_num, no_num, fin, w_mem_out;
reg [1:0] state, nextstate;
reg [3:0] indx;
parameter S0 = 0; parameter S1 = 1; parameter S2 = 2; parameter S3 = 3;
RAM_IN RAM_IN_inst1 (
.data_X (data_X),
.indx(indx)
);
RAM_OUT RAM_OUT_inst1 (
.s_rslt_Y (s_rslt_Y),
.w_mem_out (w_mem_out),
.set_ram (set_ram)
);
always # (posedge clk or negedge rst_n)
begin
if (~rst_n)
begin
set_ram <= 1;
indx <= 0;
no_num <=0;
enable <= 1;
s_sec_A <= 0;
s_sec_B <= 0;
s_rslt_Y <= 0;
state <= S0;
end
else if (clear)
begin
enable <= 0;
state <= nextstate;
no_num <= 0;
indx <= 0;
set_ram <= 1;
fin <= 1;
end
else
begin
set_ram <= 0;
state <= nextstate;
if (save_sec_A)
s_sec_A <= sec_A;
if (save_sec_B)
s_sec_B <= sec_B;
if (save_rslt_Y)
s_rslt_Y <= rslt_Y;
if (next_num)
begin
if (indx >= 9)
begin
indx <= 0; /// resetea el indice de la memoria
no_num <= 1; // se informa que no hay numeros
end
else
indx <= indx + 4'b0001;
end
end
end
always # (*)
begin
w_mem_out = 0;
sec_A = 0; sec_B = 0; rslt_Y = 0;
save_sec_A = 0; save_sec_B = 0;
save_rslt_Y = 0; clear = 0;
next_num = 0;
case (state)
S0:
begin
if (~enable)
nextstate = S0;
else
begin
sec_A = data_X + 7'b0000001;
save_sec_A = 1;
nextstate = S1;
end
end
S1: begin
sec_B = data_X - 7'b0000001;
save_sec_B = 1;
nextstate = S2;
end
S2: begin
rslt_Y = s_sec_A * s_sec_B;
save_rslt_Y = 1;
nextstate = S3;
end
S3: begin
w_mem_out = 1;
next_num = 1;
nextstate = S0;
if (no_num == 1)
clear = 1;
end
default:
nextstate = S0;
endcase
end
endmodule
This is the memory I "simulated" as a RAM for input data :
module RAM_IN (data_X, indx);
input [0:3] indx;
output [6:0] data_X;
reg [6:0] data_X;
reg [6:0] in_ram [0:9];
always # (indx)
data_X = in_ram [indx];
initial
begin
$readmemb("C:/altera/15.0/PROYECTOS/mem_prue/in_ram.txt", in_ram);
end
endmodule
and this for output data:
module RAM_OUT (s_rslt_Y, w_mem_out, set_ram);
input [13:0]s_rslt_Y;
input set_ram, w_mem_out;
reg [3:0] addr_out; // tamano de 57600 datos
reg [13:0] mem_out [0:9];
always # (w_mem_out or set_ram)
begin
if (set_ram)
addr_out = 0;
else if (w_mem_out == 1)
begin
mem_out [addr_out] = s_rslt_Y;
addr_out = addr_out + 4'b0001;
end
else
addr_out = addr_out;
end
endmodule
and The test bench:
module mem_prue1_tb ();
wire fin;
reg clk, rst_n;
mem_prue1 mem_prue1_inst1 (
.clk(clk),
.rst_n (rst_n),
.fin (fin)
);
initial
begin
rst_n <= 1;
#1 rst_n <= 0;
#2 rst_n <= 1;
clk <= 1;
end
always
begin
#5 clk = ~clk;
end
//---------------------------
integer out,i;
initial begin
out=$fopen("C:/altera/15.0/PROYECTOS/mem_prue/mem_out.txt");
end
always#(posedge clk) begin
if(fin==1)
for(i=0;i<=9;i=i+1) begin
$fdisplay(out,"%b",mem_prue1_inst1.RAM_OUT_inst1.mem_out[i]);
if(i==9)begin
$stop;
end
end
end
endmodule
So, basically now I want to substitute that "simulated" RAM for real SDRAM, I don't know what is the most practical way to do it.
Should I use QSYS, NIOS-II, or only by learning the Megawizard IP library and generating a variation of the UniPHY. I'm just learning to use the FPGA, so I'm kinda confused at this part. I want to download the proper manuals and tutorials for learn this in detail but I wish you guys could orient me.
PD: My target would be to "isolate" my logic unit from the "simulated ram" because I'm guessing if I program just like I did, it will consume logic resources and my main goal is to calculate the Area, Energy and Speed consumption of my logic ONLY, without the memory burden.
Thanks.
Your keywords, (QSYS, megawizard, uniphy) indicate Altera. If you are just going to simulate the SDRAM, you should be okay. Sometimes, bringing up that interface in a real chip gets hairy the first time.
If you are just doing simulation, I would use QSYS to generate the SDRAM controller module. If you can do DDR3, that there is the ability to generate an Example Design. If you do that, you will be able to see how the interface to the DDR3 works. In fact it should be already to go.
As an FYI, there will be more latency on the read though, so you need to be able to either wait for the response, or you need to have a pipeline architecture, where you can have multiple reads in flight simultaneously.
The "FPGAs Now What?" tutorial offers some advice (for a Xilinx platform, which apparently doesn't match your particular case) on SDRAM simulation. Basically, it boils down to finding an SDRAM vendor with an available Verilog/VHDL model, and plugging it in to a simulation testbench. (Note that these models aren't going to be synthesizeable.)
http://www.xess.com/static/media/appnotes/FpgasNowWhatBook.pdf
Altera has a tutorial for connecting the SDRAM to a Nios II system (using Qsys) on the DE1-SoC board.
ftp://ftp.altera.com/up/pub/Altera_Material/16.0/Tutorials/Verilog/DE1-SoC/Using_the_SDRAM.pdf
If you're implementing your own controller (or using a HW only IP Core), the tutorial also has the timing information for the SDRAM as well.