Segmentation fault: 11 while compiling with yosys - verilog

I'm trying to implement a Verilog module that writes in a Lattice UP5K SPRAM hardware core using the Yosys SB_SPRAM256KA block. Note that there are little or no documentation/examples about usage of this black box block. The main purpose is implementing an echo or delay in an audio digital system.
I have two clocks the frame clock lrclk and the bit clock bclk, note that each period of frame clock has 64 bit clocks periods.
I tried to, with a sensitivity list in the blck, cycle a read/write process in the SPRAM. I implement a state machina that:
S1: Put the input data in the input port of the RAM, enable the write_enable signal and set the writing pointer to RAM address.
S2: (Data supposed to be written) Disables write_enable signal and set the reading pointer to RAM address.
S3: (Data supposed to be loaded on output buffer of the RAM). Set the module output from the RAM output buffer and resets the state machine.
This is the module code:
module echo(
input wire bclk,
input wire lrclk,
input wire [DATALEN-1:0] right_in,
output reg [DATALEN-1:0] right_out,
);
localparam ADDRLEN = 14;
localparam DATALEN = 16;
reg [ADDRLEN-1:0] rd_ptr = 0;
reg [ADDRLEN-1:0] wr_ptr = (2**ADDRLEN)/2;
reg [2:0] sm = 0;
reg wren;
reg [ADDRLEN-1:0] memaddr;
reg [DATALEN-1:0] datain;
reg [DATALEN-1:0] dataout;
SB_SPRAM256KA M1 (
.ADDRESS(memaddr),
.DATAIN(datain),
.MASKWREN(4'b1111),
.WREN(wren),
.CHIPSELECT(1'b1),
.CLOCK(bclk),
.STANDBY(1'b0),
.SLEEP(1'b0),
.POWEROFF(1'b0),
.DATAOUT(dataout)
);
always #(posedge lrclk) begin
sm <= 1;
end
always #(posedge bclk) begin
if (sm === 1) begin
datain <= right_in;
wren <= 1;
memaddr <= wr_ptr;
sm <= 2;
end else if (sm === 2) begin
wren <= 0;
memaddr <= rd_ptr;
sm <= 3;
end else if (sm === 3) begin
right_out <= dataout;
wr_ptr <= (wr_ptr + 1);
rd_ptr <= (rd_ptr + 1);
sm <= 0;
end
end
endmodule
I expect to have errors on systhesis time or misfunctional behaving of the implementation, but I obtain this Yosis error:
5.11. Executing WREDUCE pass (reducing word size of cells).
Removed top 31 bits (of 32) from port B of cell main.$add$main.v:70$2 ($add).
Removed top 1 bits (of 32) from port Y of cell main.$add$main.v:70$2 ($add).
Removed top 2 bits (of 3) from FF cell main.$techmap\E1.$procdff$117 ($dff).
make: *** [main.bin] Segmentation fault: 11

.POWEROFF(1'b0) should be 1'b1 right?
See the "iCE40 SPRAM Usage Guide" for more information.

Related

Bits do not get shifted when performing shift operation in Verilog

I am trying to build an SPI module in verilog which transmits 8 bits of data, but when doing the shift operation I have noticed that shifting does not shift bits at all, while MOSI and MISO only take value of zero after the first cycle, which results in data on both side decaying to zero. What can I do to fix this?
Code for master:
module Master(input clk, input MISO,
output reg MOSI, output reg SS);
initial SS = 0;
reg [2:0] counter;
reg [7:0] Master_reg = 8'b11011011;
always # (posedge clk)
begin
if(!SS)
begin
if(^counter === 1'bx)
counter = 0;
else
counter = counter + 1;
MOSI = Master_reg[7];
Master_reg = Master_reg >> 1;
Master_reg[0] = MISO;
end
if(counter == 7)
SS = 1;
end
endmodule
Code for slave:
module Slave(input clk, input MOSI, input SS,
output reg MISO);
reg [2:0] counter;
reg [7:0] Slave_reg = 8'b11111111;
always # (posedge clk)
begin
if(!SS)
begin
if(^counter === 1'bx)
counter = 0;
else
counter = counter + 1;
MISO = Slave_reg[0];
Slave_reg = Slave_reg << 1;
Slave_reg[7] = MOSI;
end
end
endmodule
Transmission of given data (11011011 from master, 11111111 from slave) gives following result:
Edit: I am using EDA Playground as a simulator
There's a mistake in both master and slave. You're sending out the most significant bit of master_reg, but shifting that register to the right. You must shift it left instead.
Same with slave, the bit that's being sent is not the one toward which the data is shifted.
Btw, both the master and slave must shift to the same direction. Otherwise you'll get data reversed between master and slave.

I2C slave module in Verilog does not acknowledge

I wrote this I2C slave module in Verilog:
module I2CSlave(
input iSCL,
input iI2C_CLK,
inout bSDA,
output reg [7:0] odata,
output reg oread,
output wire oactive
);
reg incycle = 1'b0;
reg pSDA;
reg pSCL;
always #(posedge iI2C_CLK) begin
if ((pSCL) && (iSCL) && (pSDA) && (~bSDA)) begin
incycle <= 1;
end
if ((pSCL) && (iSCL) && (~pSDA) && (bSDA)) begin
incycle <= 0;
end
pSDA <= bSDA;
pSCL <= iSCL;
end
assign oactive = incycle;
localparam STATE_IDLE = 0;
localparam STATE_ADDR = 1;
localparam STATE_RW = 2;
localparam STATE_ACK = 3;
localparam STATE_DATA = 4;
localparam STATE_ACK2 = 5;
reg [7:0] i = 0;
reg [7:0] state = STATE_IDLE;
reg [6:0] addr = 7'h03;
reg addr_match = 1;
reg rw;
reg lSDA;
always #(posedge iSCL) lSDA <= bSDA;
assign bSDA = ((state == STATE_ACK) || (state == STATE_ACK2)) ? 0 : 1'bz;
assign oread = (state == STATE_ACK2);
assign ostate = i;
always #(negedge iSCL or negedge incycle) begin
if (~incycle) begin
state <= STATE_IDLE;
addr_match <= 1;
end
else if (addr_match) begin
case (state)
STATE_IDLE: begin
state <= STATE_ADDR;
i <= 7;
end
STATE_ADDR: begin
if (addr[i-1] != lSDA) addr_match <= 0;
if (i == 1) begin
state <= STATE_RW;
i <= i - 1;
end
else i <= i - 1;
end
STATE_RW: begin
rw <= lSDA;
state <= STATE_ACK;
end
STATE_ACK: begin
state <= STATE_DATA;
i = 7;
end
STATE_DATA : begin
odata[i] <= lSDA;
if (i == 0) state <= STATE_ACK2;
else i <= i - 1;
end
STATE_ACK2: begin
state <= STATE_DATA;
i = 7;
end
endcase
end
end
endmodule
As of now it should just read the data sent by master. It seems to work well in simulation, but when I upload it into the FPGA, sometimes everything is OK, however sometimes it does not acknowledge the data sent by master and it just seems to ignore them. I am newbie in Verilog, so I hope, this is not a silly question.
One possible cause for random fails while running on real hardware is that you didn't synchronize inputs.
You are sampling slowly changing signals (i2c bus will have a long slopes) that are truly asynchronous to your design's clock. Depending on your luck, you will have random violations for setup/hold times of your fpga's d-flops, which results in metastability issues. The same value in the register might be treated differently in multiple parts of the chip. That will wreak havoc in your i2c slave's logic.
You must synchronize asynchronous inputs, in the simplest case passing it through a couple of registers before feeding it to the module's fsm.
You have several issues with your code which could cause mismatch in behavior in simulation and synthesis. For example, the following is not synthesizable and is ignored by synthesis tools. So, your initial state would be different. Check your logs for warnings. Do not use declaration assignments for regs. (ok for wires).
reg [7:0] i = 0;
reg [7:0] state = STATE_IDLE;
reg [6:0] addr = 7'h03;
reg addr_match = 1;
The above means that you initialization does not work.
You messed up blocking and non-blocking assignments in the state machine. Make sure that you use nbas in all places where 'i = 7'. it should be
i <= 7;
And make sure that you test enough initialization and different conditions in simulation.

Verilog : uart on FPGA and simulation behavioural differences

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.

Lattice iCE40-HX8K Board - UART

I have the following verilog code for my Lattice iCE40-HX8K Board:
uart.v:
module uart(input clk, output TXD);
reg [3:0] count;
reg [9:0] data;
reg z;
initial begin
data[9:0] = 10'b1000000000; // Startbit = 1, Stopbit = 0
z = 0;
end
always#(posedge clk)
begin
if(count == 1250) //9600x per Second (1250) = Baudrate
begin
count <= 0;
TXD = data[z];
z = z + 1;
if(z == 10)
begin
z = 0;
end
else
begin
end
end
else
begin
count <= count + 1;
end
end
endmodule
For receiving the UART-Data I use gtkterm under Ubuntu 14.04.
I have set the baudrate in gtkterm to 9600.
If I now program my FPGA with the code I receive once per programming a
hex "00" (irrespective of the 8 usage-bits).
Can anybody give me a hint what is wrong?
Thank you for your support.
There are at least two obvious problems with your design:
Your count is only 4 bits wide, thus it cannot count to 1250. It must be at least 11 bits wide to be able to count to 1250.
Also your z is only 1 bit wide, so it can only hold the values 0 and 1. It must be at least 4 bits wide to be able to count to 10.
You should also read up on blocking vs. non-blocking assignments. The way you use blocking assignments in sequential logic can lead to race conditions in the verilog simulation model.
You should always write testbenches for your HDL code and simulate it before trying to run it in hardware. A testbench for your design would be as easy as:
module uart_testbench;
reg clk = 1;
always #5 clk = ~clk;
uart uut (
.clk(clk)
);
initial begin
$dumpfile("uart.vcd");
$dumpvars(0, uut);
repeat (1000000) #(posedge clk);
$finish;
end
endmodule

My verilog VGA driver causes the screen to flicker (Basys2)

I'm trying to recreate Adventure(1979) in Verilog and so far I have character movement, collision and map generation done. It didn't flicker that much before I separated the maps into modules now it flickers constantly. When I was looking up this issue, I found out that the clock on the Basys2 board is pretty noisy and could be the culprit. However, putting the maps into modules shouldn't have made it worse unless I messed something up. Any idea what happened?
Here's my map generator:
module map_generator(clk_vga, reset, CurrentX, CurrentY, HBlank, VBlank, playerPosX, playerPosY, mapData
);
input clk_vga;
input reset;
input [9:0]CurrentX;
input [8:0]CurrentY;
input HBlank;
input VBlank;
input [9:0]playerPosX;
input [8:0]playerPosY;
output [7:0]mapData;
reg [7:0]mColor;
reg [5:0]currentMap = 0;
wire [7:0]startCastle;
StartCastle StartCastle(
.clk_vga(clk_vga),
.CurrentX(CurrentX),
.CurrentY(CurrentY),
.mapData(startCastle)
);
always #(posedge clk_vga) begin
if(reset)begin
currentMap <= 0;
end
end
always #(posedge clk_vga) begin
if(HBlank || VBlank) begin
mColor <= 0;
end
else begin
if(currentMap == 4'b0000) begin
mColor[7:0] <= startCastle[7:0];
end
//Add more maps later
end
end
assign mapData[7:0] = mColor[7:0];
endmodule
Here's the startCastle:
module StartCastle(clk_vga, CurrentX, CurrentY, active, mapData);
input clk_vga;
input [9:0]CurrentX;
input [8:0]CurrentY;
input active;
output [7:0]mapData;
reg [7:0]mColor;
always #(posedge clk_vga) begin
if(CurrentY < 40) begin
mColor[7:0] <= 8'b11100000;
end
else if(CurrentX < 40) begin
mColor[7:0] <= 8'b11100000;
end
else if(~(CurrentX < 600)) begin
mColor[7:0] <= 8'b11100000;
end
else if((~(CurrentY < 440) && (CurrentX < 260)) || (~(CurrentY < 440) && ~(CurrentX < 380))) begin
mColor[7:0] <= 8'b11100000;
end else
mColor[7:0] <= 8'b00011100;
end
assign mapData = mColor;
endmodule
Here's the VGA driver which is connected to my top module:
module vga_driver(clk_50MHz, vs_vga, hs_vga, RED, GREEN, BLUE, HBLANK, VBLANK, CURX, CURY, COLOR, CLK_DATA, RESET);
input clk_50MHz;
output vs_vga;
output hs_vga;
output [2:0] RED;
output [2:0] GREEN;
output [1:0] BLUE;
output HBLANK;
output VBLANK;
reg VS = 0;
reg HS = 0;
input RESET;
//current client data
input [7:0] COLOR;
output CLK_DATA;
output [9:0] CURX;
output [8:0] CURY;
//##### Module constants (http://tinyvga.com/vga-timing/640x480#60Hz)
parameter HDisplayArea = 640; // horizontal display area
parameter HLimit = 800; // maximum horizontal amount (limit)
parameter HFrontPorch = 16; // h. front porch
parameter HBackPorch = 48; // h. back porch
parameter HSyncWidth = 96; // h. pulse width
parameter VDisplayArea = 480; // vertical display area
parameter VLimit = 525; // maximum vertical amount (limit)
parameter VFrontPorch = 10; // v. front porch
parameter VBackPorch = 33; // v. back porch
parameter VSyncWidth = 2; // v. pulse width
//##### Local variables
wire clk_25MHz;
reg [9:0] CurHPos = 0; //maximum of HLimit (2^10 - 1 = 1023)
reg [9:0] CurVPos = 0; //maximum of VLimit
reg HBlank_reg, VBlank_reg, Blank = 0;
reg [9:0] CurrentX = 0; //maximum of HDisplayArea
reg [8:0] CurrentY = 0; //maximum of VDisplayArea (2^9 - 1 = 511)
//##### Submodule declaration
clock_divider clk_div(.clk_in(clk_50MHz), .clk_out(clk_25MHz));
//shifts the clock by half a period (negates it)
//see timing diagrams for a better understanding of the reason for this
clock_shift clk_shift(.clk_in(clk_25MHz), .clk_out(CLK_DATA));
//simulate the vertical and horizontal positions
always #(posedge clk_25MHz) begin
if(CurHPos < HLimit-1) begin
CurHPos <= CurHPos + 1;
end
else begin
CurHPos <= 0;
if(CurVPos < VLimit-1)
CurVPos <= CurVPos + 1;
else
CurVPos <= 0;
end
if(RESET) begin
CurHPos <= 0;
CurVPos <= 0;
end
end
//##### VGA Logic (http://tinyvga.com/vga-timing/640x480#60Hz)
//HSync logic
always #(posedge clk_25MHz)
if((CurHPos < HSyncWidth) && ~RESET)
HS <= 1;
else
HS <= 0;
//VSync logic
always #(posedge clk_25MHz)
if((CurVPos < VSyncWidth) && ~RESET)
VS <= 1;
else
VS <= 0;
//Horizontal logic
always #(posedge clk_25MHz)
if((CurHPos >= HSyncWidth + HFrontPorch) && (CurHPos < HSyncWidth + HFrontPorch + HDisplayArea) || RESET)
HBlank_reg <= 0;
else
HBlank_reg <= 1;
//Vertical logic
always #(posedge clk_25MHz)
if((CurVPos >= VSyncWidth + VFrontPorch) && (CurVPos < VSyncWidth + VFrontPorch + VDisplayArea) || RESET)
VBlank_reg <= 0;
else
VBlank_reg <= 1;
//Do not output any color information when we are in the vertical
//or horizontal blanking areas. Set a boolean to keep track of this.
always #(posedge clk_25MHz)
if((HBlank_reg || VBlank_reg) && ~RESET)
Blank <= 1;
else
Blank <= 0;
//Keep track of the current "real" X position. This is the actual current X
//pixel location abstracted away from all the timing details
always #(posedge clk_25MHz)
if(HBlank_reg && ~RESET)
CurrentX <= 0;
else
CurrentX <= CurHPos - HSyncWidth - HFrontPorch;
//Keep track of the current "real" Y position. This is the actual current Y
//pixel location abstracted away from all the timing details
always #(posedge clk_25MHz)
if(VBlank_reg && ~RESET)
CurrentY <= 0;
else
CurrentY <= CurVPos - VSyncWidth - VFrontPorch;
assign CURX = CurrentX;
assign CURY = CurrentY;
assign VBLANK = VBlank_reg;
assign HBLANK = HBlank_reg;
assign hs_vga = HS;
assign vs_vga = VS;
//Respects VGA Blanking areas
assign RED = (Blank) ? 3'b000 : COLOR[7:5];
assign GREEN = (Blank) ? 3'b000 : COLOR[4:2];
assign BLUE = (Blank) ? 2'b00 : COLOR[1:0];
endmodule
clk_div:
module clock_divider(clk_in, clk_out);
input clk_in;
output clk_out;
reg clk_out = 0;
always #(posedge clk_in)
clk_out <= ~clk_out;
endmodule
clk_shift:
module clock_shift(clk_in, clk_out);
input clk_in;
output clk_out;
assign clk_out = ~clk_in;
endmodule
I'm posting this as an answer because I cannot put a photo in a comment.
Is this what your design looks like?
My only guess ATM is that you might have misplaced some ports during instantiation of vga_driver and/or map_generator (if you used the old style instantiation). Nevertheless, I'm going to check VGA timmings, as I can see a strange vertical line at the left of the screen, as if the hblank interval was visible.
By the way: I've changed the way you generate the display. You use regs for HS, VS, etc, which get updated the next clock cycle. I treat display generation as a FSM, so outputs come from combinational blocks triggered by certain values (or range of values) from the counters. Besides, I start horizontal and vertical counters so position (0,0) measured in pixel coordinates in the screen actually maps to values (0,0) from horizontal and vertical counters, so no arithmetic needed.
This is my version of VGA display generation:
module videosyncs (
input wire clk,
input wire [2:0] rin,
input wire [2:0] gin,
input wire [1:0] bin,
output reg [2:0] rout,
output reg [2:0] gout,
output reg [1:0] bout,
output reg hs,
output reg vs,
output wire [10:0] hc,
output wire [10:0] vc
);
/* http://www.abramovbenjamin.net/calc.html */
// VGA 640x480#60Hz,25MHz
parameter htotal = 800;
parameter vtotal = 524;
parameter hactive = 640;
parameter vactive = 480;
parameter hfrontporch = 16;
parameter hsyncpulse = 96;
parameter vfrontporch = 11;
parameter vsyncpulse = 2;
parameter hsyncpolarity = 0;
parameter vsyncpolarity = 0;
reg [10:0] hcont = 0;
reg [10:0] vcont = 0;
reg active_area;
assign hc = hcont;
assign vc = vcont;
always #(posedge clk) begin
if (hcont == htotal-1) begin
hcont <= 0;
if (vcont == vtotal-1) begin
vcont <= 0;
end
else begin
vcont <= vcont + 1;
end
end
else begin
hcont <= hcont + 1;
end
end
always #* begin
if (hcont>=0 && hcont<hactive && vcont>=0 && vcont<vactive)
active_area = 1'b1;
else
active_area = 1'b0;
if (hcont>=(hactive+hfrontporch) && hcont<(hactive+hfrontporch+hsyncpulse))
hs = hsyncpolarity;
else
hs = ~hsyncpolarity;
if (vcont>=(vactive+vfrontporch) && vcont<(vactive+vfrontporch+vsyncpulse))
vs = vsyncpolarity;
else
vs = ~vsyncpolarity;
end
always #* begin
if (active_area) begin
gout = gin;
rout = rin;
bout = bin;
end
else begin
gout = 3'h00;
rout = 3'h00;
bout = 2'h00;
end
end
endmodule
Which is instantiated by your vga_driver module, which becomes nothing but a wrapper for this module:
module vga_driver (
input wire clk_25MHz,
output wire vs_vga,
output wire hs_vga,
output wire [2:0] RED,
output wire [2:0] GREEN,
output wire [1:0] BLUE,
output wire HBLANK,
output wire VBLANK,
output [9:0] CURX,
output [8:0] CURY,
input [7:0] COLOR,
input wire RESET
);
assign HBLANK = 0;
assign VBLANK = 0;
videosyncs syncgen (
.clk(clk_25MHz),
.rin(COLOR[7:5]),
.gin(COLOR[4:2]),
.bin(COLOR[1:0]),
.rout(RED),
.gout(GREEN),
.bout(BLUE),
.hs(hs_vga),
.vs(vs_vga),
.hc(CURX),
.vc(CURY)
);
endmodule
Note that in map_generator, the first if statement in this always block will never be true. We can forget about it, as the VGA display module will blank RGB outputs when needed.
always #(posedge clk_vga) begin
if(HBlank || VBlank) begin //
mColor <= 0; // Never reached
end //
else begin //
if(currentMap == 4'b0000) begin
mColor[7:0] <= startCastle[7:0];
end
//Add more maps later
end
end
Using the same approach, I've converted the map generator module to be a combinational module. For example, for map 0 (the castle -without the castle, I see-) it is like this:
module StartCastle(
input wire [9:0] CurrentX,
input wire [8:0] CurrentY,
output wire [7:0] mapData
);
reg [7:0] mColor;
assign mapData = mColor;
always #* begin
if(CurrentY < 40) begin
mColor[7:0] <= 8'b11100000;
end
else if(CurrentX < 40) begin
mColor[7:0] <= 8'b11100000;
end
else if(~(CurrentX < 600)) begin
mColor[7:0] <= 8'b11100000;
end
else if((~(CurrentY < 440) && (CurrentX < 260)) || (~(CurrentY < 440) && ~(CurrentX < 380))) begin
mColor[7:0] <= 8'b11100000;
end else
mColor[7:0] <= 8'b00011100;
end
endmodule
Just a FSM whose output is the colour that goes in a pixel. The input being the coordinates of the current pixel.
So when it is time to display map 0, map_generator simply switches to it based upon the current value of currentMap
module map_generator (
input wire clk,
input wire reset,
input wire [9:0]CurrentX,
input wire [8:0]CurrentY,
input wire HBlank,
input wire VBlank,
input wire [9:0]playerPosX,
input wire [8:0]playerPosY,
output wire [7:0]mapData
);
reg [7:0] mColor;
assign mapData = mColor;
reg [5:0]currentMap = 0;
wire [7:0] castle_map;
StartCastle StartCastle(
.CurrentX(CurrentX),
.CurrentY(CurrentY),
.mapData(castle_map)
);
always #(posedge clk) begin
if(reset) begin
currentMap <= 0;
end
end
always #* begin
if(currentMap == 6'b000000) begin
mColor = castle_map;
end
//Add more maps later
end
endmodule
This may look like a lot of comb logic is generated and so glitches may happen. It's actually very fast, no noticeable glitches on screen, and you can use the actual current x and y coordinates to choose what to display on screen. Thus, no need for an inverted clock. My final version of your design has only one 25MHz clock.
By the way, you want to keep device dependent constructions away from your design, placing things like clock generators in separate modules that will be connected to your design in the top module, which should be the only device dependent module.
So, I've written a device-agnostic adventure module, which will contain the entire game:
module adventure (
input clk_vga,
input reset,
output vs_vga,
output hs_vga,
output [2:0] RED,
output [2:0] GREEN,
output [1:0] BLUE
);
wire HBLANK, VBLANK;
wire [7:0] COLOR;
wire [9:0] CURX;
wire [8:0] CURY;
wire [9:0] playerPosX = 10'd320; // no actually used in the design yet
wire [8:0] playerPosY = 9'd240; // no actually used in the design yet
vga_driver the_screen (.clk_25MHz(clk_vga),
.vs_vga(vs_vga),
.hs_vga(hs_vga),
.RED(RED),
.GREEN(GREEN),
.BLUE(BLUE),
.HBLANK(HBLANK),
.VBLANK(VBLANK),
.CURX(CURX),
.CURY(CURY),
.COLOR(COLOR)
);
map_generator the_mapper (.clk(clk_vga),
.reset(reset),
.CurrentX(CURX),
.CurrentY(CURY),
.HBlank(HBLANK),
.VBlank(VBLANK),
.playerPosX(playerPosX),
.playerPosY(playerPosY),
.mapData(COLOR)
);
endmodule
This module is not complete: it lacks inputs from joystick or any other input device to update player current position. For now, player current position is fixed.
The top level design (TLD) is written exclusively for the FPGA trainer you have. It is here where you need to generate proper clocks using your device's available resources, such as the DCM in Spartan 3/3E devices.
module tld_basys(
input wire clk_50MHz,
input wire RESET,
output wire vs_vga,
output wire hs_vga,
output wire [2:0] RED,
output wire [2:0] GREEN,
output wire [1:0] BLUE
);
wire clk_25MHz;
dcm_clocks gen_vga_clock (
.CLKIN_IN(clk_50MHz),
.CLKDV_OUT(clk_25MHz)
);
adventure the_game (.clk_vga(clk_25MHz),
.reset(RESET),
.vs_vga(vs_vga),
.hs_vga(hs_vga),
.RED(RED),
.GREEN(GREEN),
.BLUE(BLUE)
);
endmodule
The DCM generated clocks goes in this module (generated by the Xilinx Core Generator)
module dcm_clocks (CLKIN_IN,
CLKDV_OUT
);
input CLKIN_IN;
output CLKDV_OUT;
wire CLKFB_IN;
wire CLKFX_BUF;
wire CLKDV_BUF;
wire CLKIN_IBUFG;
wire CLK0_BUF;
wire GND_BIT;
assign GND_BIT = 0;
BUFG CLKDV_BUFG_INST (.I(CLKDV_BUF),
.O(CLKDV_OUT));
IBUFG CLKIN_IBUFG_INST (.I(CLKIN_IN),
.O(CLKIN_IBUFG));
BUFG CLK0_BUFG_INST (.I(CLK0_BUF),
.O(CLKFB_IN));
DCM_SP #(.CLKDV_DIVIDE(2.0), .CLKIN_DIVIDE_BY_2("FALSE"),
.CLKIN_PERIOD(20.000), .CLKOUT_PHASE_SHIFT("NONE"),
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), .DFS_FREQUENCY_MODE("LOW"),
.DLL_FREQUENCY_MODE("LOW"), .DUTY_CYCLE_CORRECTION("TRUE"),
.FACTORY_JF(16'hC080), .PHASE_SHIFT(0), .STARTUP_WAIT("FALSE") )
DCM_SP_INST (.CLKFB(CLKFB_IN),
.CLKIN(CLKIN_IBUFG),
.DSSEN(GND_BIT),
.PSCLK(GND_BIT),
.PSEN(GND_BIT),
.PSINCDEC(GND_BIT),
.RST(GND_BIT),
.CLKDV(CLKDV_BUF),
.CLKFX(),
.CLKFX180(),
.CLK0(CLK0_BUF),
.CLK2X(),
.CLK2X180(),
.CLK90(),
.CLK180(),
.CLK270(),
.LOCKED(),
.PSDONE(),
.STATUS());
endmodule
Although it is safe (for Xilinx devices) to use a simple clock divider as you did. If you fear that the synthesizer won't treat your divided clock as an actual clock, add a BUFG primitive to route the output from the divider to a global buffer so it can be used as a clock with no problems (see the module above for an example on how to do this).
As a final note, you may want to add more independency from the final device, by using 24-bit colours for your graphics. At the TLD, you will use the actual number of bits per colour component you really have, but if you move from the Basys2 with 8-bit colour trainer board to the, say, Nexys4 board, with 12-bit colour, you will automatically enjoy a richer output display.
Now, it looks like this (no vertical bars at the left, and colours seem to be more vibrant)

Resources