SPQI Computer Interface - Verilog Code

Verilog Code

module RS232_V3m( sysclk, rad_triggers_in, RxD, TxD, Switches, LEDs, sevenSegLED_out, sevenSegPos_out, JB_U);

// Nexys3: Family: Spartan 6; Device: XC6SLX16; Package: CSG324; Speed: -3

(* LOC = "V10" *) input sysclk;

(* CLOCK_DEDICATED_ROUTE = "FALSE", LOC = "E11 G11 P11 T12" *) input [3:0] rad_triggers_in;

//trigger (counter) signal 0 is pin JA_U[0]

//trigger (counter) signal 1 is pin JA_U[3]

//trigger (counter) signal 2 is pin JD_U[0]

//trigger (counter) signal 3 is pin JD_U[3]

(* LOC = "J6" *)input RxD; //JC_L[2] //need external RS232 connector

(* LOC = "F2" *) output TxD; //JC_L[3]

(* LOC = "T5 V8 U8 N8 M8 V9 T9 T10" *) input [7:0] Switches;

(* LOC = "L14 N14 M14 U18 U17 T18 T17" *) output [6:0] sevenSegLED_out;

(* LOC = "P17 P18 N15 N16" *) output [3:0] sevenSegPos_out;

(* LOC = "T11 R11 N11 M11 V15 U15 V16 U16" *)output [7:0] LEDs;

(* LOC = "L3 L4 K1 K2" *) output [3:0] JB_U;

parameter SYS_CLOCK_FREQ = 100_000_000; //system clock speed in Hz (check reg clk_div width!)

parameter MYVERSION = 16'h1112;

parameter BIG_COUNTER = 31;

//localparam SYS_CLOCK_FREQ = 50_000_000; //system clock speed in Hz (check reg clk_div width!)

defparam MyHHMMSS.SYS_CLOCK_FREQ = SYS_CLOCK_FREQ;

defparam my_rs232receiver.SYS_CLOCK_FREQ = SYS_CLOCK_FREQ;

defparam my_rs232transmitter.SYS_CLOCK_FREQ = SYS_CLOCK_FREQ;

wire master_reset; //master reset for all counters and one shots

wire [15:0] sysclkfreqMHz = SYS_CLOCK_FREQ / 1_000_000; //sys_clock frequency in MHz

/*******setup the reference clocks ************************************/

/* DAY::HH:MM:SS Clock Code ***************************************/

wire clk_miliseconds, clk_seconds, clk_minutes, clk_hours, clk_days;

wire [15:0] miliseconds;

wire [15:0] seconds;

wire [15:0] minutes;

wire [15:0] hours;

wire [15:0] days;

HHMMSS2a MyHHMMSS(sysclk, master_reset, clk_miliseconds, miliseconds, clk_seconds, seconds, clk_minutes, minutes, clk_hours, hours, clk_days, days);

/**************SET COINCIDENCE WINDOW **************************************************/

//

// Byte Sent: ~ Tau = 1 sysclk cycle which is the shortest and the default!

// The coincidence window is set through the one shot's clock. This clock is set

// the RS232 byte received from the computer.

// The byte send by the computer corresponds to:

// window = 1: Byte Sent: A Tau = 2 sysclk cycle

// window = 2: Byte Sent: B Tau = 4 sysclk cycle

// window = 3: Byte Sent: C Tau = 6 sysclk cycle

// etc. i.e. n sysclck cycle = 2(winow -1)

// window = 0: Byte Sent: ~ Tau = 1 sysclk cycle which is the shortest and the default!

reg [5:0] ntau_sysclk = 61; //number of sysclock cycles for coincidence window

reg [5:0] onesh_sysclk_counter = 0;

reg one_shot_clk_reg = 0;

wire one_shot_clk;

always @ (posedge sysclk)begin

if (onesh_sysclk_counter == ntau_sysclk ) begin //reset each ntau_sysclk

onesh_sysclk_counter <= 0;

one_shot_clk_reg <= ~one_shot_clk_reg;

end

else begin

onesh_sysclk_counter <= onesh_sysclk_counter + 1;

end

end

assign one_shot_clk =( ntau_sysclk == 61 ) ? sysclk: //input from RS232: 'p'

one_shot_clk_reg;

/********* set up the one-shots for all the trigger inputs **********************/

OneShotV2 OneShotC0( one_shot_clk, rad_triggers_in[0], oneshot0_out);

OneShotV2 OneShotC1( one_shot_clk, rad_triggers_in[1], oneshot1_out);

OneShotV2 OneShotC2( one_shot_clk, rad_triggers_in[2], oneshot2_out);

OneShotV2 OneShotC3( one_shot_clk, rad_triggers_in[3], oneshot3_out);

//OneShotV2( clk, asynctrigger_in, trig_out);

//OneShot OneShotC3( one_shot_clk, master_reset, miliseconds[0], oneshot3_out);

/********* set up the counters for all the straight trigger inputs **********************/

wire [BIG_COUNTER:0] finalcount0_out;

wire [BIG_COUNTER:0] finalcount1_out;

wire [BIG_COUNTER:0] finalcount2_out;

wire [BIG_COUNTER:0] finalcount3_out;

CECounter32 myCECounter0(one_shot_clk, master_reset, oneshot0_out, finalcount0_out);

CECounter32 myCECounter1(one_shot_clk, master_reset, oneshot1_out, finalcount1_out);

CECounter32 myCECounter2(one_shot_clk, master_reset, oneshot2_out, finalcount2_out);

CECounter32 myCECounter3(one_shot_clk, master_reset, oneshot3_out, finalcount3_out);

//testing only

assign JB_U = {clk_miliseconds, sysclk, one_shot_clk, oneshot3_out};

/********* set up the counters for all the 2 counter coincidence inputs **********************/

wire [BIG_COUNTER:0] final_coinc_01_out;

wire [BIG_COUNTER:0] final_coinc_02_out;

wire [BIG_COUNTER:0] final_coinc_03_out;

wire [BIG_COUNTER:0] final_coinc_12_out;

wire [BIG_COUNTER:0] final_coinc_13_out;

wire [BIG_COUNTER:0] final_coinc_23_out;

wire coinc_01, coinc_02, coinc_03, coinc_12, coinc_13, coinc_23;

assign coinc_01 = oneshot0_out & oneshot1_out;

assign coinc_02 = oneshot0_out & oneshot2_out;

assign coinc_03 = oneshot0_out & oneshot3_out;

assign coinc_12 = oneshot1_out & oneshot2_out;

assign coinc_13 = oneshot1_out & oneshot3_out;

assign coinc_23 = oneshot2_out & oneshot3_out;

CECounter32 myCECoincCounter01(one_shot_clk, master_reset, coinc_01, final_coinc_01_out);

CECounter32 myCECoincCounter02(one_shot_clk, master_reset, coinc_02, final_coinc_02_out);

CECounter32 myCECoincCounter03(one_shot_clk, master_reset, coinc_03, final_coinc_03_out);

CECounter32 myCECoincCounter12(one_shot_clk, master_reset, coinc_12, final_coinc_12_out);

CECounter32 myCECoincCounter13(one_shot_clk, master_reset, coinc_13, final_coinc_13_out);

CECounter32 myCECoincCounter23(one_shot_clk, master_reset, coinc_23, final_coinc_23_out);

/********* set up the counters for all the 3 counter coincidence inputs **********************/

wire [BIG_COUNTER:0] final_coinc_012_out;

wire [BIG_COUNTER:0] final_coinc_013_out;

wire [BIG_COUNTER:0] final_coinc_023_out;

wire [BIG_COUNTER:0] final_coinc_123_out;

wire coinc_012, coinc_013, coinc_023, coinc_123;

assign coinc_012 = oneshot0_out & oneshot1_out & oneshot2_out;

assign coinc_013 = oneshot0_out & oneshot1_out & oneshot3_out;

assign coinc_023 = oneshot0_out & oneshot2_out & oneshot3_out;

assign coinc_123 = oneshot1_out & oneshot2_out & oneshot3_out;

CECounter32 myCECoincCounter012(one_shot_clk, master_reset, coinc_012, final_coinc_012_out);

CECounter32 myCECoincCounter013(one_shot_clk, master_reset, coinc_013, final_coinc_013_out);

CECounter32 myCECoincCounter023(one_shot_clk, master_reset, coinc_023, final_coinc_023_out);

CECounter32 myCECoincCounter123(one_shot_clk, master_reset, coinc_123, final_coinc_123_out);

/********* set up the counters for all the 4 counter coincidence inputs **********************/

wire [BIG_COUNTER:0] final_coinc_0123_out;

wire coinc_0123;

assign coinc_0123 = oneshot0_out & oneshot1_out & oneshot2_out & oneshot3_out;

CECounter32 myCECoincCounter0123(one_shot_clk, master_reset, coinc_0123, final_coinc_0123_out);

/***************END OF COINCIDENCE COUNTER SETUP **********************************/

/***********************************************************************************/

/* **************** RS 232 PORT STUFF ************************** */

//RECEIVER ////////////////////////////////////////////////

wire RxD_data_ready;

wire [7:0] RxD_data;

//receiver

async_receiver my_rs232receiver(.clk(sysclk), .RxD(RxD), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data));

// Trigger Oneshot for byte received

reg datarec = 0;

reg datarec_reset = 0;

always @(posedge RxD_data_ready or posedge datarec_reset)

if (datarec_reset) begin

datarec <= 0;

end

else begin

datarec <= 1;

end

// TRANSMITTER /////////////////////////////////////////////////

reg [7:0] GPin;

wire TxD_Transmit;

wire TxD_BUSY;

async_transmitter my_rs232transmitter(.clk(sysclk), .TxD(TxD), .TxD_start(TxD_Transmit), .TxD_data(GPin), .TxD_busy( TxD_BUSY));

/***********************************FSM For RS232***********************/

/* RS232 OUTPUT FORMAT: ALL are 2 byte blocks separated by comma: (without blank spaces); at the end a CR.

/: DAYS, HH, MM, SEC, MilisSEC, Counter0, Counter1, Counter 2, Counter3, Coincidence01, Coincidence 12 <CR> */

parameter TWOBYTECOUNTERS = 21; //number of FOUR!!!! byte pairs to be sent out:

// 15 from rad counters, 5 from clock + 1 sys clock frequency info

parameter BYTESOUT = 4*TWOBYTECOUNTERS; //counter bytes to be sent out

parameter BYTESMAX = 2*BYTESOUT+TWOBYTECOUNTERS-1; //total bytes to be sent including commas

reg [7:0] bytecounter = 0;

reg [8*BYTESOUT-1:0] DataOut = 0;

reg [2:0] state = 0;

parameter STATE_IDLE = 0;

parameter STATE_COUNTER = 1;

parameter STATE_RS232_TRANSMIT = 2;

parameter COMMA = 8'h2c;

parameter CR = 8'h0d;

parameter LF = 8'h0a;

reg [3:0] commactr = 0; //counts space to send out commas after every two bytes

reg counter_resets = 0;

//works and sends out two bytes of data via RS232

always@( posedge sysclk )

case( state)

STATE_IDLE: begin

if( datarec) begin //trigger data received; reset everything and get ready to send out data

datarec_reset <= 1;

counter_resets <= 1;

DataOut <= {16'h0000, days, 16'h0000, hours,16'h0000, minutes,16'h0000, seconds, 16'h0000, miliseconds, 16'h0000, sysclkfreqMHz,

finalcount0_out, finalcount1_out, finalcount2_out, finalcount3_out,

final_coinc_01_out, final_coinc_02_out, final_coinc_03_out,

final_coinc_12_out, final_coinc_13_out, final_coinc_23_out,

final_coinc_012_out, final_coinc_013_out, final_coinc_023_out, final_coinc_123_out,

final_coinc_0123_out

};

bytecounter <= 0;

state <= STATE_COUNTER;

commactr <= 0;

//Store value sent from compute in RS232Data_FromComputer register to set coincidence window

//subtract 65 ('A') from it to find mulitple of sys_clk coincidence window, i.e.,

//tau = (RxD_data-65 + 1)*tau_sysclock

ntau_sysclk <= RxD_data-65; //watch for upper / lower case letters!

end

else

state <= STATE_IDLE;

end

STATE_COUNTER: begin

if( (bytecounter < BYTESMAX) & ( commactr < 8) ) begin //do it by nibbles to convert to ASCII

datarec_reset <= 0; //maybe move to end to prevent retrigger?

counter_resets <= 0;

//GPin <= tmpradcounts0[8*BYTESOUT-1:8*(BYTESOUT-1)];

DataOut <= {DataOut[8*(BYTESOUT-1)-1+4:0 ],4'h0};

state <= STATE_RS232_TRANSMIT;

commactr <= commactr + 1;

if(DataOut[8*BYTESOUT-1:8*(BYTESOUT-1)+4]< 10) //check for numbers or letteres

GPin <= DataOut[8*BYTESOUT-1:8*(BYTESOUT-1)+4]+48;

else

GPin <= DataOut[8*BYTESOUT-1:8*(BYTESOUT-1)+4]+55;

end

else if( (bytecounter < BYTESMAX) & ( commactr == 8) ) begin //send out a comma after every 4 bytes

GPin <= COMMA;

state <= STATE_RS232_TRANSMIT;

commactr <= 0;

end

else if( bytecounter == BYTESMAX ) begin //send out CR and finish

GPin <= CR;

state <= STATE_RS232_TRANSMIT;

end

else begin

state <= STATE_IDLE; //check???????????????????????

end

bytecounter <= bytecounter + 1;

end

STATE_RS232_TRANSMIT: begin

if( TxD_BUSY)

state <= STATE_RS232_TRANSMIT;

else begin

state <= STATE_COUNTER;

end

end

endcase

assign TxD_Transmit = (state == STATE_RS232_TRANSMIT )&(! TxD_BUSY);

//assign BNC2 = TxD; //_Transmit; // signal from board to computer

OneShotV2 OneShotMasterReset( one_shot_clk, counter_resets, master_reset);

//assign master_reset = counter_resets;

//set up for display and instantiate it

//assign LEDs = miliseconds_counter[14:6]; //helpful for debugging

assign LEDs = Switches[7] ? 8'h00 : 8'h00 ; //finalcount1_out; // miliseconds_counter[14:6]; //helpful for debugging

wire [15:0] display_value;

assign display_value =(Switches[5:0] == 6'b00_0000 ) ? miliseconds: //miliseconds

(Switches[5:0] == 6'b00_0001 ) ? seconds: // seconds

(Switches[5:0] == 6'b00_0010 ) ? minutes: //minutes

(Switches[5:0] == 6'b00_0011 ) ? hours: //hours

(Switches[5:0] == 6'b00_0100 ) ? finalcount0_out: //

(Switches[5:0] == 6'b00_0101 ) ? finalcount1_out: //

(Switches[5:0] == 6'b00_0110 ) ? finalcount2_out: //

(Switches[5:0] == 6'b00_0111 ) ? finalcount3_out: //

(Switches[5:0] == 6'b00_1000 ) ? final_coinc_01_out: //

(Switches[5:0] == 6'b00_1001 ) ? final_coinc_02_out: //

(Switches[5:0] == 6'b00_1010 ) ? final_coinc_03_out: //

(Switches[5:0] == 6'b00_1011 ) ? final_coinc_12_out: //

(Switches[5:0] == 6'b00_1100 ) ? final_coinc_13_out: //

(Switches[5:0] == 6'b00_1101 ) ? final_coinc_23_out: //

(Switches[5:0] == 6'b00_1110 ) ? final_coinc_012_out: //

(Switches[5:0] == 6'b00_1111 ) ? final_coinc_013_out: //

(Switches[5:0] == 6'b01_0000 ) ? final_coinc_023_out: //

(Switches[5:0] == 6'b01_0001 ) ? final_coinc_123_out: //

(Switches[5:0] == 6'b01_0011 ) ? final_coinc_0123_out: //

(Switches[5:0] == 6'b11_1111 ) ? MYVERSION: //

16'hFFFF; //default value

HexDisplayV1 myHexDisp(sysclk, display_value, Switches[6], Switches[7], sevenSegLED_out, sevenSegPos_out);

endmodule

module OneShotV2( clk, asynctrigger_in, trig_out);

input clk;

input asynctrigger_in;

output trig_out; //lasts exactly one clock cycle

reg trig_set = 0;

reg trig_reset = 0;

/*************** ASYNC INPUT to ONE SHOT *****************************/

// One Shot Part: sets output (oneshot_out) HI for one cycle when "asynctrigger_in" is HI

// during posedge sysclk. Otherwise, "oneshot_out" stays LO.

// Therefore, one shot output is synced with sysclk.

always@(posedge asynctrigger_in or posedge trig_reset)

if( trig_reset)

trig_set <= 0;

else

trig_set <=1;

always@( posedge clk)

if( trig_set)

trig_reset <= 1;

else

trig_reset <=0;

assign trig_out = trig_reset;

/************** END of ONE SHOT *******************************/

endmodule

module CECounter32(sysclk, reset, CE_in, finalcount_out);

/******************** 32 bit COUNTER with CE INPUT and LAST COUNT OUTPUT *********************/

// Counter with CE: is activated by sysclk but it increments only

// during one sysclk cycle when "CE_in" is HI.

// At "reset" countvalue is stored into final_count registry.

input sysclk;

input reset;

input CE_in; //counter enable signal (keep HI for only one cycle!)

output reg [31:0] finalcount_out = 0;

reg [31:0] internal_counter = 0;

always @(posedge sysclk )

if (reset) begin

internal_counter <= 0;

end

else if (CE_in) begin

if( internal_counter != 32'hffff_ffff) //prevent overflow

internal_counter <= internal_counter + 1;

end

//eliminate the problem when reset is more than one sysclock cycle long

// in which case in the previous version the finalcount_out was set 0

always @(posedge reset )

finalcount_out <= internal_counter;

/******************** END OF COUNTER ***************************/

endmodule

-- Main.KurtWick - 13 Dec 2012

  • Verilog code attached