It is just a snippet. It is from DDR3 tutorial using memory interface generator (mig) and the wrapper, etc.: https://alchitry.com/ddr3-memory
The whole top_module:
module au_top (
input clk, // 100MHz clock
input rst_n, // reset button (active low)
output led [8], // 8 user controllable LEDs
input usb_rx, // USB->Serial input
output usb_tx, // USB->Serial output
/* DDR3 Connections */
inout ddr3_dq[16],
inout ddr3_dqs_n[2],
inout ddr3_dqs_p[2],
output ddr3_addr[14],
output ddr3_ba[3],
output ddr3_ras_n,
output ddr3_cas_n,
output ddr3_we_n,
output ddr3_reset_n,
output ddr3_ck_p,
output ddr3_ck_n,
output ddr3_cke,
output ddr3_cs_n,
output ddr3_dm[2],
output ddr3_odt
) {
sig rst; // reset signal
clk_wiz_0 clk_wiz;
// DDR3 Interface - connect inouts directly
mig_wrapper mig (.ddr3_dq(ddr3_dq), .ddr3_dqs_n(ddr3_dqs_n), .ddr3_dqs_p(ddr3_dqs_p));
.clk(mig.ui_clk) {
.rst(rst) {
fsm state = {WRITE_DATA, WRITE_CMD, READ_CMD, WAIT_READ, DELAY};
dff ctr[24];
dff address[8];
dff led_reg[8];
}
}
always {
/* Clock Wizard Connections */
clk_wiz.clk_in1 = clk; // 100MHz in
clk_wiz.reset = !rst_n; // reset signal
/* DDR3 Connections */
ddr3_addr = mig.ddr3_addr;
ddr3_ba = mig.ddr3_ba;
ddr3_ras_n = mig.ddr3_ras_n;
ddr3_cas_n = mig.ddr3_cas_n;
ddr3_we_n = mig.ddr3_we_n;
ddr3_reset_n = mig.ddr3_reset_n;
ddr3_ck_p = mig.ddr3_ck_p;
ddr3_ck_n = mig.ddr3_ck_n;
ddr3_cke = mig.ddr3_cke;
ddr3_cs_n = mig.ddr3_cs_n;
ddr3_dm = mig.ddr3_dm;
ddr3_odt = mig.ddr3_odt;
mig.sys_clk = clk_wiz.clk_out1; // 100MHz clock
mig.clk_ref = clk_wiz.clk_out2; // 200MHz clock
mig.sys_rst = !clk_wiz.locked; // reset when clk_wiz isn't locked
rst = mig.sync_rst; // use the reset signal from the mig core
led = led_reg.q; // set leds to show led_reg value
usb_tx = usb_rx; // echo the serial data
// default values
mig.mem_in.en = 0;
mig.mem_in.cmd = 3bx;
mig.mem_in.addr = 28bx;
mig.mem_in.wr_data = 128bx;
mig.mem_in.wr_mask = 0;
mig.mem_in.wr_en = 0;
case (state.q) {
state.WRITE_DATA:
mig.mem_in.wr_en = 1;
mig.mem_in.wr_data = address.q;
if (mig.mem_out.wr_rdy)
state.d = state.WRITE_CMD;
state.WRITE_CMD:
mig.mem_in.en = 1;
mig.mem_in.cmd = 0; // 0 = write
mig.mem_in.addr = c{address.q, 3b000}; // first three bits of addr are for the 8 words in wr_data
if (mig.mem_out.rdy) {
address.d = address.q + 1;
state.d = state.WRITE_DATA;
if (address.q == 8hFF) {
state.d = state.READ_CMD;
address.d = 0;
}
}
state.READ_CMD:
mig.mem_in.en = 1;
mig.mem_in.cmd = 1; // 1 = read
mig.mem_in.addr = c{address.q, 3b000};
if (mig.mem_out.rdy)
state.d = state.WAIT_READ;
state.WAIT_READ:
if (mig.mem_out.rd_valid) {
led_reg.d = mig.mem_out.rd_data[7:0];
state.d = state.DELAY;
address.d = address.q + 1;
}
state.DELAY:
ctr.d = ctr.q + 1; // delay so we can see the value
if (&ctr.q)
state.d = state.READ_CMD;
}
}
}
In the case statement, state.WRITE_DATA, the author writes an address (address.q) to memory and after 256 times it ‘replays’ them from memory and shows on the LED’s.
In the tutorial it says that address.q can be replaced with other values which is true if they are assigned directly as in: mig.mem_in.wr_data = 8hAA; or any other 8-bit value. But when I try bring a byte received from the UART receive module it does not work, mig.mem_in.wr_data = rx.data;. But the data is actually there! I can light the LED’s with that value anywhere in the top module as long as it is not in a case or if statement. The byte will not pass through an obvious barrier. I can better explain this on a phone call. After reading about the attempts to correct issues with the 1.2.7 Alchitry Labs to Lucid V2, it looks like this issue is being corrected. I’ve spent a lot of time trying every which was to get the case statement to work with a variable value (rx.data) and it does not work; even if I assign rx.data = 8hAA in the always{} code and try to use it in the case statement, it will not work but it does if I use LED=rx.data; outside the case statement! It just won’t cross some sort of barrier. If I’m using the case statement wrong then how would you do it?