mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Initial SD Card reader.
This commit is contained in:
parent
221dbe92b2
commit
ec0d2bc7d7
55
wally-pipelined/proposed-sdc.txt
Normal file
55
wally-pipelined/proposed-sdc.txt
Normal file
@ -0,0 +1,55 @@
|
||||
SD Flash interface
|
||||
|
||||
regsiter map:
|
||||
1. clock divider
|
||||
2. address
|
||||
3. data register
|
||||
4. command register
|
||||
5. size register
|
||||
Number of bytes to read or write.
|
||||
6. status register
|
||||
1. bits 11 to 0: bytes currently in the buffer
|
||||
2. bits 12 to 29: reservered
|
||||
3. bit 30: fault
|
||||
4. bit 31: busy
|
||||
5. bits XLEN-1 to 32: reservered
|
||||
|
||||
|
||||
|
||||
non dma read operation
|
||||
1. write the address regsiter
|
||||
2. write the command register to read
|
||||
3. wait for interrupt or pool on status
|
||||
4. Check status for fault and number of bytes.
|
||||
5. read the data register for 512 bytes. (64 ld, or 128 lw)
|
||||
|
||||
|
||||
non dma write operation
|
||||
1. write address register
|
||||
2. write data register for 512 bytes. (64 sd, or 128 sw)
|
||||
3. write command register to write data to flash
|
||||
4. wait for interrupt or pool on status
|
||||
5. check status for fault and number of bytes written.
|
||||
|
||||
implement dma transfers later
|
||||
|
||||
|
||||
interrupts
|
||||
1. operation done
|
||||
2. bus error (more of an exception)
|
||||
Occurs if attempting to do an operation while the flash controller is busy.
|
||||
ie. if status[31] is set generate an interrupt
|
||||
This is tricky in a multiprocessor environment.
|
||||
|
||||
|
||||
|
||||
|
||||
tasks
|
||||
1. [-] Remove all AFRL identifiers
|
||||
2. [X] get the existing sdc compiled on wally.
|
||||
1. [X] use wally primatives over tcore's
|
||||
3. build abhlite interface with the above registers and necessary fsm.
|
||||
1. [ ] The sd card reader uses a 4 bit data interface. We can change this to be something
|
||||
more pratical.
|
||||
4. write test programs
|
||||
5. [X] Convert VHDL to system verilog
|
72
wally-pipelined/src/sdc/clkdivider.sv
Normal file
72
wally-pipelined/src/sdc/clkdivider.sv
Normal file
@ -0,0 +1,72 @@
|
||||
///////////////////////////////////////////
|
||||
// clock divider.sv
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: clock divider for sd flash
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module clkdivider #(parameter integer g_COUNT_WIDTH)
|
||||
(
|
||||
input logic [g_COUNT_WIDTH-1:0] i_COUNT_IN_MAX, //((Divide by value)/2) - 1
|
||||
input logic i_EN, //Enable frequency division of i_clk
|
||||
input logic i_CLK, // 1.2 GHz Base clock
|
||||
input logic i_RST, // at start: clears flip flop and loads counter,
|
||||
// i_RST must NOT be a_RST, it needs to be synchronized with the 50 MHz Clock to load the
|
||||
// counter's initial value
|
||||
output logic o_CLK // frequency divided clock
|
||||
);
|
||||
|
||||
|
||||
logic [g_COUNT_WIDTH-1:0] r_count_out; // wider for sign
|
||||
logic w_counter_overflowed;
|
||||
|
||||
logic r_fd_Q;
|
||||
logic w_fd_D;
|
||||
|
||||
logic w_load;
|
||||
|
||||
assign w_load = i_RST | w_counter_overflowed; // reload when zero occurs or when set by outside
|
||||
|
||||
counter #(.WIDTH(g_COUNT_WIDTH)) // wider for sign, this way the (MSB /= '1') only for zero
|
||||
my_counter (.clk(i_CLK),
|
||||
.Load(w_load), // reload when zero occurs or when set by outside
|
||||
.CountIn(i_COUNT_IN_MAX), // negative signed integer
|
||||
.CountOut(r_count_out),
|
||||
.Enable(1'b1), // ALWAYS COUNT
|
||||
.reset(1'b0)); // no reset, only load
|
||||
|
||||
|
||||
assign w_counter_overflowed = r_count_out[g_COUNT_WIDTH-1] == '0;
|
||||
|
||||
flopenr #(1) toggle_flip_flop
|
||||
(.d(w_fd_D),
|
||||
.q(r_fd_Q),
|
||||
.clk(i_CLK),
|
||||
.reset(i_RST), // reset when told by outside
|
||||
.en(w_counter_overflowed)); // only update when counter overflows
|
||||
|
||||
assign w_fd_D = ~ r_fd_Q;
|
||||
|
||||
assign o_CLK = i_EN ? r_fd_Q : i_CLK;
|
||||
|
||||
endmodule
|
54
wally-pipelined/src/sdc/counter.sv
Normal file
54
wally-pipelined/src/sdc/counter.sv
Normal file
@ -0,0 +1,54 @@
|
||||
///////////////////////////////////////////
|
||||
// counter.sv
|
||||
//
|
||||
// Written: Ross Thompson
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: basic up counter
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module counter #(parameter integer WIDTH=32)
|
||||
(
|
||||
input logic [WIDTH-1:0] CountIn,
|
||||
output logic [WIDTH-1:0] CountOut,
|
||||
input logic Load,
|
||||
input logic Enable,
|
||||
input logic clk,
|
||||
input logic reset);
|
||||
|
||||
logic [WIDTH-1:0] NextCount;
|
||||
logic [WIDTH-1:0] count_q;
|
||||
logic [WIDTH-1:0] CountP1;
|
||||
|
||||
flopenr #(WIDTH) reg1(.clk,
|
||||
.reset,
|
||||
.en(Enable | Load),
|
||||
.d(NextCount),
|
||||
.q(CountOut));
|
||||
|
||||
assign CountP1 = CountOut + 1'b1;
|
||||
|
||||
// mux between load and P1
|
||||
assign NextCount = Load ? CountIn : CountP1;
|
||||
|
||||
endmodule
|
||||
|
||||
|
62
wally-pipelined/src/sdc/crc16_sipo_np_ce.sv
Normal file
62
wally-pipelined/src/sdc/crc16_sipo_np_ce.sv
Normal file
@ -0,0 +1,62 @@
|
||||
///////////////////////////////////////////
|
||||
// crc16 sipo np ce
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: CRC16 generator SIPO using register_ce
|
||||
// w/o appending any zero-bits to the message
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module crc16_sipo_np_ce
|
||||
(input logic CLK, // sequential device
|
||||
input logic RST, // initial calue of CRC register must be "0000_0000_0000_0000"
|
||||
input logic i_enable, // input is valid
|
||||
input logic i_message_bit,
|
||||
output logic [15:0] o_crc16);
|
||||
|
||||
logic [15:0] w_crc16_d;
|
||||
|
||||
flopenr #(16) crc16reg(.clk(CLK),
|
||||
.reset(RST),
|
||||
.en(i_enable),
|
||||
.d(w_crc16_d),
|
||||
.q(o_crc16));
|
||||
|
||||
assign w_crc16_d[15] = o_crc16[14];
|
||||
assign w_crc16_d[14] = o_crc16[13];
|
||||
assign w_crc16_d[13] = o_crc16[12];
|
||||
assign w_crc16_d[12] = o_crc16[11] ^ (i_message_bit ^ o_crc16[15]);
|
||||
assign w_crc16_d[11] = o_crc16[10];
|
||||
assign w_crc16_d[10] = o_crc16[9];
|
||||
assign w_crc16_d[9] = o_crc16[8];
|
||||
assign w_crc16_d[8] = o_crc16[7];
|
||||
assign w_crc16_d[7] = o_crc16[6];
|
||||
assign w_crc16_d[6] = o_crc16[5];
|
||||
assign w_crc16_d[5] = o_crc16[4] ^ (i_message_bit ^ o_crc16[15]);
|
||||
assign w_crc16_d[4] = o_crc16[3];
|
||||
assign w_crc16_d[3] = o_crc16[2];
|
||||
assign w_crc16_d[2] = o_crc16[1];
|
||||
assign w_crc16_d[1] = o_crc16[0];
|
||||
assign w_crc16_d[0] = i_message_bit ^ o_crc16[15];
|
||||
|
||||
|
||||
endmodule
|
66
wally-pipelined/src/sdc/crc7_pipo.sv
Normal file
66
wally-pipelined/src/sdc/crc7_pipo.sv
Normal file
@ -0,0 +1,66 @@
|
||||
///////////////////////////////////////////
|
||||
// crc7 sipo np ce
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: takes 40 bits of input, generates 7 bit CRC after a single
|
||||
// clock cycle!
|
||||
// w/o appending any zero-bits to the message
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module crc7_pipo
|
||||
(input logic [39:0] i_DATA,
|
||||
input logic i_CRC_ENABLE,
|
||||
input logic RST,
|
||||
input logic CLK,
|
||||
output logic [6:0] o_CRC);
|
||||
|
||||
logic [6:0] r_lfsr_q;
|
||||
logic [6:0] w_lfsr_d;
|
||||
|
||||
assign o_CRC = r_lfsr_q;
|
||||
|
||||
assign w_lfsr_d[0] = r_lfsr_q[1] ^ r_lfsr_q[2] ^ r_lfsr_q[4] ^ r_lfsr_q[6] ^ i_DATA[0] ^ i_DATA[4] ^ i_DATA[7] ^ i_DATA[8] ^ i_DATA[12] ^ i_DATA[14] ^ i_DATA[15] ^ i_DATA[16] ^ i_DATA[18] ^ i_DATA[20] ^ i_DATA[21] ^ i_DATA[23] ^ i_DATA[24] ^ i_DATA[30] ^ i_DATA[31] ^ i_DATA[34] ^ i_DATA[35] ^ i_DATA[37] ^ i_DATA[39];
|
||||
|
||||
assign w_lfsr_d[1] = r_lfsr_q[2] ^ r_lfsr_q[3] ^ r_lfsr_q[5] ^ i_DATA[1] ^ i_DATA[5] ^ i_DATA[8] ^ i_DATA[9] ^ i_DATA[13] ^ i_DATA[15] ^ i_DATA[16] ^ i_DATA[17] ^ i_DATA[19] ^ i_DATA[21] ^ i_DATA[22] ^ i_DATA[24] ^ i_DATA[25] ^ i_DATA[31] ^ i_DATA[32] ^ i_DATA[35] ^ i_DATA[36] ^ i_DATA[38];
|
||||
|
||||
assign w_lfsr_d[2] = r_lfsr_q[0] ^ r_lfsr_q[3] ^ r_lfsr_q[4] ^ r_lfsr_q[6] ^ i_DATA[2] ^ i_DATA[6] ^ i_DATA[9] ^ i_DATA[10] ^ i_DATA[14] ^ i_DATA[16] ^ i_DATA[17] ^ i_DATA[18] ^ i_DATA[20] ^ i_DATA[22] ^ i_DATA[23] ^ i_DATA[25] ^ i_DATA[26] ^ i_DATA[32] ^ i_DATA[33] ^ i_DATA[36] ^ i_DATA[37] ^ i_DATA[39];
|
||||
|
||||
assign w_lfsr_d[3] = r_lfsr_q[0] ^ r_lfsr_q[2] ^ r_lfsr_q[5] ^ r_lfsr_q[6] ^ i_DATA[0] ^ i_DATA[3] ^ i_DATA[4] ^ i_DATA[8] ^ i_DATA[10] ^ i_DATA[11] ^ i_DATA[12] ^ i_DATA[14] ^ i_DATA[16] ^ i_DATA[17] ^ i_DATA[19] ^ i_DATA[20] ^ i_DATA[26] ^ i_DATA[27] ^ i_DATA[30] ^ i_DATA[31] ^ i_DATA[33] ^ i_DATA[35] ^ i_DATA[38] ^ i_DATA[39];
|
||||
|
||||
assign w_lfsr_d[4] = r_lfsr_q[1] ^ r_lfsr_q[3] ^ r_lfsr_q[6] ^ i_DATA[1] ^ i_DATA[4] ^ i_DATA[5] ^ i_DATA[9] ^ i_DATA[11] ^ i_DATA[12] ^ i_DATA[13] ^ i_DATA[15] ^ i_DATA[17] ^ i_DATA[18] ^ i_DATA[20] ^ i_DATA[21] ^ i_DATA[27] ^ i_DATA[28] ^ i_DATA[31] ^ i_DATA[32] ^ i_DATA[34] ^ i_DATA[36] ^ i_DATA[39];
|
||||
|
||||
assign w_lfsr_d[5] = r_lfsr_q[0] ^ r_lfsr_q[2] ^ r_lfsr_q[4] ^ i_DATA[2] ^ i_DATA[5] ^ i_DATA[6] ^ i_DATA[10] ^ i_DATA[12] ^ i_DATA[13] ^ i_DATA[14] ^ i_DATA[16] ^ i_DATA[18] ^ i_DATA[19] ^ i_DATA[21] ^ i_DATA[22] ^ i_DATA[28] ^ i_DATA[29] ^ i_DATA[32] ^ i_DATA[33] ^ i_DATA[35] ^ i_DATA[37];
|
||||
|
||||
assign w_lfsr_d[6] = r_lfsr_q[0] ^ r_lfsr_q[1] ^ r_lfsr_q[3] ^ r_lfsr_q[5] ^ i_DATA[3] ^ i_DATA[6] ^ i_DATA[7] ^ i_DATA[11] ^ i_DATA[13] ^ i_DATA[14] ^ i_DATA[15] ^ i_DATA[17] ^ i_DATA[19] ^ i_DATA[20] ^ i_DATA[22] ^ i_DATA[23] ^ i_DATA[29] ^ i_DATA[30] ^ i_DATA[33] ^ i_DATA[34] ^ i_DATA[36] ^ i_DATA[38];
|
||||
|
||||
|
||||
|
||||
flopenr #(7)
|
||||
lfsrReg(.clk(CLK),
|
||||
.reset(RST),
|
||||
.en(i_CRC_ENABLE),
|
||||
.d(w_lfsr_d),
|
||||
.q(r_lfsr_q));
|
||||
|
||||
|
||||
endmodule
|
61
wally-pipelined/src/sdc/crc7_sipo_np_ce.sv
Normal file
61
wally-pipelined/src/sdc/crc7_sipo_np_ce.sv
Normal file
@ -0,0 +1,61 @@
|
||||
///////////////////////////////////////////
|
||||
// crc16 sipo np ce
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: CRC7 generator SIPO using register_ce
|
||||
// w/o appending any zero-bits othe message
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module crc7_sipo_np_ce
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst,// initial CRC value must be b"000_0000"
|
||||
input logic i_enable,
|
||||
input logic i_message_bit,
|
||||
output logic [6:0] o_crc7);
|
||||
|
||||
|
||||
logic [6:0] w_crc7_d;
|
||||
logic [6:0] r_crc7_q;
|
||||
|
||||
flopenr #(7)
|
||||
crc7Reg(.clk(clk),
|
||||
.reset(rst),
|
||||
.en(i_enable),
|
||||
.d(w_crc7_d),
|
||||
.q(r_crc7_q));
|
||||
|
||||
assign w_crc7_d[6] = r_crc7_q[5];
|
||||
assign w_crc7_d[5] = r_crc7_q[4];
|
||||
assign w_crc7_d[4] = r_crc7_q[3];
|
||||
assign w_crc7_d[3] = r_crc7_q[2] ^ (i_message_bit ^ r_crc7_q[6]);
|
||||
assign w_crc7_d[2] = r_crc7_q[1];
|
||||
assign w_crc7_d[1] = r_crc7_q[0];
|
||||
assign w_crc7_d[0] = i_message_bit ^ r_crc7_q[6];
|
||||
|
||||
assign o_crc7 = r_crc7_q;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
51
wally-pipelined/src/sdc/piso_generic_ce.sv
Normal file
51
wally-pipelined/src/sdc/piso_generic_ce.sv
Normal file
@ -0,0 +1,51 @@
|
||||
///////////////////////////////////////////
|
||||
// piso generic ce
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified:
|
||||
//
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module piso_generic_ce #(parameter integer g_BUS_WIDTH)
|
||||
(
|
||||
input logic clk,
|
||||
input logic i_load,
|
||||
input logic [g_BUS_WIDTH-1:0] i_data,
|
||||
input logic i_en,
|
||||
output o_data);
|
||||
|
||||
|
||||
logic [g_BUS_WIDTH-1:0] w_reg_d;
|
||||
logic [g_BUS_WIDTH-1:0] r_reg_q;
|
||||
|
||||
flopenr #(g_BUS_WIDTH)
|
||||
shiftReg(.clk(clk),
|
||||
.reset(1'b0),
|
||||
.en(1'b1),
|
||||
.d(w_reg_d),
|
||||
.q(r_reg_q));
|
||||
|
||||
assign o_data = i_en ? r_reg_q[g_BUS_WIDTH - 1] : 1'b1;
|
||||
assign w_reg_d = i_load ? i_data :
|
||||
i_en ? {r_reg_q[g_BUS_WIDTH - 2 : 0], 1'b1} :
|
||||
r_reg_q[g_BUS_WIDTH - 1 : 0];
|
||||
|
||||
endmodule
|
45
wally-pipelined/src/sdc/regfile_p2r1w1_nibo.sv
Normal file
45
wally-pipelined/src/sdc/regfile_p2r1w1_nibo.sv
Normal file
@ -0,0 +1,45 @@
|
||||
///////////////////////////////////////////
|
||||
// regfile_p2r1w1_nibo
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified: 2 port register file with 1 read and 1 write
|
||||
//
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module regfile_p2r1w1_nibo #(parameter integer DEPTH = 10, parameter integer WIDTH = 4)
|
||||
(input logic clk,
|
||||
input logic we1,
|
||||
input logic [DEPTH-1:0] ra1,
|
||||
output logic [WIDTH-1:0] rd1,
|
||||
input logic [DEPTH-1:0] wa1,
|
||||
input logic [WIDTH-1:0] wd1);
|
||||
|
||||
logic [WIDTH-1:0] regs [2**DEPTH-1:0];
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(we1) begin
|
||||
regs[wa1] <= wd1;
|
||||
end
|
||||
end
|
||||
|
||||
assign rd1 = regs[ra1];
|
||||
|
||||
endmodule
|
51
wally-pipelined/src/sdc/regfile_p2r1w1bwen.sv
Normal file
51
wally-pipelined/src/sdc/regfile_p2r1w1bwen.sv
Normal file
@ -0,0 +1,51 @@
|
||||
///////////////////////////////////////////
|
||||
// regfile_p2r1w1bwen
|
||||
//
|
||||
// Written: Ross Thompson September 18, 2021
|
||||
// Modified: 2 port register file with 1 read and 1 write
|
||||
//
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module regfile_p2r1w1bwen #(parameter integer DEPTH = 10, parameter integer WIDTH = 4)
|
||||
(input logic clk,
|
||||
input logic we1,
|
||||
input logic [WIDTH-1:0] we1bit,
|
||||
input logic [DEPTH-1:0] ra1,
|
||||
output logic [WIDTH-1:0] rd1,
|
||||
input logic [DEPTH-1:0] wa1,
|
||||
input logic [WIDTH-1:0] wd1);
|
||||
|
||||
logic [WIDTH-1:0] regs [2**DEPTH-1:0];
|
||||
integer i;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(we1) begin
|
||||
for (i=0; i < WIDTH; i++) begin
|
||||
if(we1bit[i]) begin
|
||||
regs[wa1][i] <= wd1[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign rd1 = regs[ra1];
|
||||
|
||||
endmodule
|
94
wally-pipelined/src/sdc/sd_clk_fsm.sv
Normal file
94
wally-pipelined/src/sdc/sd_clk_fsm.sv
Normal file
@ -0,0 +1,94 @@
|
||||
///////////////////////////////////////////
|
||||
// sd_clk_fsm.sv
|
||||
//
|
||||
// Written: Ross Thompson September 19, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Controls clock dividers.
|
||||
// Replaces s_disable_sd_clocks, s_select_hs_clk, s_enable_hs_clk
|
||||
// in sd_cmd_fsm.vhd. Attempts to correct issues with oversampling and
|
||||
// under-sampling of control signals (for counter_cmd), that were present in my
|
||||
// previous design.
|
||||
// This runs on 50 MHz.
|
||||
// sd_cmd_fsm will run on SD_CLK_Gated (50 MHz or 400 KHz, selected by this)
|
||||
// asynchronous reset is used for both sd_cmd_fsm and for this.
|
||||
// It must be synchronized with 50 MHz and held for a minimum period of a full
|
||||
// 400 KHz pulse width.
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module sd_clk_fsm
|
||||
(
|
||||
input logic CLK,
|
||||
input logic i_RST,
|
||||
output logic o_DONE,
|
||||
input logic i_START,
|
||||
input logic i_FATAL_ERROR,
|
||||
output logic o_HS_TO_INIT_CLK_DIVIDER_RST, // resets clock divider that is going from 50 MHz to 400 KHz
|
||||
output logic o_SD_CLK_SELECTED, // which clock is selected ('0'=HS or '1'=init)
|
||||
output logic o_G_CLK_SD_EN); // Turns gated clock (G_CLK_SD) off and on
|
||||
|
||||
|
||||
logic [3:0] w_next_state;
|
||||
logic [3:0] r_curr_state;
|
||||
|
||||
|
||||
// clock selection
|
||||
parameter c_sd_clk_init = 1'b1;
|
||||
parameter c_sd_clk_hs = 1'b0;
|
||||
|
||||
// States
|
||||
localparam s_reset = 4'b0000;
|
||||
localparam s_enable_init_clk = 4'b0001; // enable 400 KHz
|
||||
localparam s_disable_sd_clocks = 4'b0010;
|
||||
localparam s_select_hs_clk = 4'b0011;
|
||||
localparam s_enable_hs_clk = 4'b0100;
|
||||
localparam s_done = 4'b0101;
|
||||
localparam s_disable_sd_clocks_2 = 4'b0110; // if error occurs
|
||||
localparam s_select_init_clk = 4'b0111; // if error occurs
|
||||
localparam s_safe_state = 4'b1111; //always provide a safe state return if all states are not used
|
||||
|
||||
flopenr #(4) stateReg(.clk(CLK),
|
||||
.reset(i_RST),
|
||||
.en(1'b1),
|
||||
.d(w_next_state),
|
||||
.q(r_curr_state));
|
||||
|
||||
assign w_next_state = i_RST ? s_reset :
|
||||
r_curr_state == s_reset | (r_curr_state == s_enable_init_clk & ~i_START) | (r_curr_state == s_select_init_clk) ? s_enable_init_clk :
|
||||
r_curr_state == s_enable_init_clk & i_START ? s_disable_sd_clocks :
|
||||
r_curr_state == s_disable_sd_clocks ? s_select_hs_clk :
|
||||
r_curr_state == s_select_hs_clk ? s_enable_hs_clk :
|
||||
r_curr_state == s_enable_hs_clk | (r_curr_state == s_done & ~i_FATAL_ERROR) ? s_done :
|
||||
r_curr_state == s_done & i_FATAL_ERROR ? s_disable_sd_clocks_2 :
|
||||
r_curr_state == s_disable_sd_clocks_2 ? s_select_init_clk :
|
||||
s_safe_state;
|
||||
|
||||
|
||||
assign o_HS_TO_INIT_CLK_DIVIDER_RST = r_curr_state == s_reset;
|
||||
|
||||
assign o_SD_CLK_SELECTED = (r_curr_state == s_select_hs_clk) | (r_curr_state == s_enable_hs_clk) | (r_curr_state == s_done) ? c_sd_clk_hs : c_sd_clk_init;
|
||||
|
||||
assign o_G_CLK_SD_EN = (r_curr_state == s_enable_init_clk) | (r_curr_state == s_enable_hs_clk) | (r_curr_state == s_done);
|
||||
|
||||
assign o_DONE = r_curr_state == s_done;
|
||||
|
||||
endmodule
|
||||
|
554
wally-pipelined/src/sdc/sd_cmd_fsm.sv
Normal file
554
wally-pipelined/src/sdc/sd_cmd_fsm.sv
Normal file
@ -0,0 +1,554 @@
|
||||
///////////////////////////////////////////
|
||||
// sd_clk_fsm.sv
|
||||
//
|
||||
// Written: Ross Thompson September 19, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Finite state machine for the SD CMD bus
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module sd_cmd_fsm
|
||||
(
|
||||
|
||||
input logic CLK, // HS
|
||||
//i_SLOWER_CLK : in std_logic;
|
||||
input logic i_RST, // reset FSM,
|
||||
// MUST COME OUT OF RESET
|
||||
// SYNCHRONIZED TO THE 1.2 GHZ CLOCK!
|
||||
output logic o_TIMER_LOAD, o_TIMER_EN, // Timer
|
||||
output logic [18:0] o_TIMER_IN,
|
||||
input logic [18:0] i_TIMER_OUT,
|
||||
output logic o_COUNTER_LOAD, o_COUNTER_EN, // Counter
|
||||
output logic [7:0] o_COUNTER_IN,
|
||||
input logic [7:0] i_COUNTER_OUT,
|
||||
output logic o_SD_CLK_EN, // Clock Gaters
|
||||
input logic i_CLOCK_CHANGE_DONE, // Communication with CLK_FSM
|
||||
output logic o_START_CLOCK_CHANGE, // Communication with CLK_FSM
|
||||
output logic o_IC_RST, o_IC_EN, o_IC_UP_DOWN, // Instruction counter
|
||||
input logic [3:0] i_IC_OUT, // stop when you get to 10 because that is CMD17
|
||||
input logic [1:0] i_USES_DAT,
|
||||
input logic [6:0] i_OPCODE,
|
||||
input logic [2:0] i_R_TYPE,
|
||||
// bit masks
|
||||
input logic [31:0] i_NO_REDO_MASK,
|
||||
input logic [31:0] i_NO_REDO_ANS,
|
||||
input logic [31:0] i_NO_ERROR_MASK,
|
||||
input logic [31:0] i_NO_ERROR_ANS,
|
||||
output logic o_SD_CMD_OE, // Enable ouptut on tri-state SD_CMD line
|
||||
// TX Components
|
||||
output logic o_TX_PISO40_LOAD, o_TX_PISO40_EN, // Shift register for TX command head
|
||||
output logic o_TX_PISO8_LOAD, o_TX_PISO8_EN, // Shift register for TX command tail
|
||||
output logic o_TX_CRC7_PIPO_RST, o_TX_CRC7_PIPO_EN, // Parallel-to-Parallel CRC7 Generator
|
||||
output logic [1:0] o_TX_SOURCE_SELECT, // What gets sent to CMD_TX
|
||||
// TX Memory
|
||||
output logic o_CMD_TX_IS_CMD55_RST,
|
||||
output logic o_CMD_TX_IS_CMD55_EN, // '1' means that the command that was just sent has index
|
||||
// 55, so the subsequent command is to be
|
||||
// viewed as ACMD by the SD card.
|
||||
// RX Components
|
||||
input logic i_SD_CMD_RX, // serial response input on SD_CMD
|
||||
output logic o_RX_SIPO48_RST, o_RX_SIPO48_EN, // Shift Register for all 48 bits of Response
|
||||
|
||||
input logic [39:8] i_RESPONSE_CONTENT, // last 32 bits of RX_SIPO_40_OUT
|
||||
input logic [45:40] i_RESPONSE_INDEX, // 6 bits from RX_SIPO_40_OUT
|
||||
output logic o_RX_CRC7_SIPO_RST, o_RX_CRC7_SIPO_EN, // Serial-to-parallel CRC7 Generator
|
||||
input logic [6:0] i_RX_CRC7,
|
||||
// RX Memory
|
||||
output logic o_RCA_REGISTER_RST, o_RCA_REGISTER_EN, // Relative Card Address
|
||||
// Communication to sd_dat_fsm
|
||||
output logic o_CMD_TX_DONE, // begin waiting for DAT_RX to complete
|
||||
input logic i_DAT_RX_DONE, // now go to next state since data block rx was completed
|
||||
input logic i_ERROR_CRC16, // repeat last command
|
||||
input logic i_ERROR_DAT_TIMES_OUT,
|
||||
// Commnuication to core
|
||||
output logic o_READY_FOR_READ, // tell core that I have completed initialization
|
||||
output logic o_SD_RESTARTING, // inform core the need to restart
|
||||
input logic i_READ_REQUEST, // core tells me to execute CMD17
|
||||
// Communication to Host
|
||||
output logic o_DAT_ERROR_FD_RST,
|
||||
output logic [2:0] o_ERROR_CODE_Q, // Indicates what caused the fatal error
|
||||
output logic o_FATAL_ERROR, // SD Card is damaged beyond recovery, restart entire initialization procedure of card
|
||||
input logic LIMIT_SD_TIMERS
|
||||
);
|
||||
|
||||
|
||||
|
||||
logic [4:0] w_next_state, r_curr_state;
|
||||
logic w_resend_last_command, w_rx_crc7_check, w_rx_index_check, w_rx_bad_crc7, w_rx_bad_index, w_rx_bad_reply, w_bad_card;
|
||||
|
||||
logic [31:0] w_redo_result, w_error_result;
|
||||
logic w_ACMD41_init_done;
|
||||
logic w_fail_cnt_en, w_fail_count_rst;
|
||||
logic [10:0] r_fail_count_out;
|
||||
|
||||
logic w_ACMD41_busy_timer_START, w_ACMD41_times_out_FLAG, w_ACMD41_busy_timer_RST; //give up after 1000 ms of ACMD41
|
||||
logic [2:0] w_ERROR_CODE_D, r_ERROR_CODE_Q ; // Error Codes for fatal error on SD CMD FSM
|
||||
logic w_error_code_rst, w_error_code_en;
|
||||
logic [18:0] Timer_In;
|
||||
|
||||
|
||||
localparam s_reset_clear_error_reg = 5'b00000;
|
||||
localparam s_idle_supply_no_clk = 5'b00001;
|
||||
localparam s_idle_supply_sd_clk = 5'b00010;
|
||||
localparam s_ld_head = 5'b00011;
|
||||
localparam s_tx_head = 5'b00100;
|
||||
localparam s_ld_tail = 5'b00101;
|
||||
localparam s_tx_tail = 5'b00110;
|
||||
localparam s_setup_rx = 5'b00111;
|
||||
localparam s_idle_ncc = 5'b01000;
|
||||
localparam s_fetch_next_cmd = 5'b01001;
|
||||
localparam s_rx_48 = 5'b01010;
|
||||
localparam s_rx_136 = 5'b01011;
|
||||
localparam s_error_no_response = 5'b01100;
|
||||
localparam s_idle_for_dat = 5'b01101;
|
||||
localparam s_error_bad_card = 5'b01110;
|
||||
localparam s_idle_nrc = 5'b01111;
|
||||
localparam s_count_attempt = 5'b10000;
|
||||
localparam s_reset_from_error = 5'b10001;
|
||||
//localparam s_enable_hs_clk = 5'b10010;
|
||||
localparam s_idle_for_start_bit = 5'b10011;
|
||||
localparam s_fetch_prev_cmd = 5'b10100; // use to resend previous cmd55 if acmd is resent
|
||||
// localparam s_setup_rx_b = 5'b10110;
|
||||
// localparam s_idle_for_start_bit_b= 5'b10111;
|
||||
// localparam s_rx_48_b = 5'b11000;
|
||||
// localparam s_rx_136_b = 5'b11001;
|
||||
localparam s_error_dat_time_out = 5'b11010; // don't advance states if the dat fsm times out
|
||||
localparam s_idle_for_clock_change = 5'b11011; // replaces s_disable_sd_clocks, s_select_hs_clk, s_enable_hs_clk
|
||||
localparam s_study_response = 5'b11100; // Do error checking here
|
||||
localparam s_idle_for_read_request = 5'b11101; // After power up and initialization sequence is completed
|
||||
localparam s_Error_TX_Failed = 5'b11110; // when fail_cnt_out exceeds c_max_attempts
|
||||
|
||||
localparam c_MAX_ATTEMPTS = 3; // Give up sending a command after 3 failed attempts
|
||||
// (except ACMD41) so the processor is not locked up forever
|
||||
|
||||
localparam c_response_type_R0_NONE = 0;
|
||||
localparam c_response_type_R1_NORMAL = 1;
|
||||
localparam c_response_type_R2_CID_CSD = 2;
|
||||
localparam c_response_type_R3_OCR = 3;
|
||||
localparam c_response_type_R6_RCA = 6;
|
||||
localparam c_response_type_R7_CIC = 7;
|
||||
|
||||
localparam c_start_bit = 1'b0;
|
||||
|
||||
localparam c_DAT_none = 2'b00;
|
||||
localparam c_DAT_busy = 2'b01;
|
||||
localparam c_DAT_wide = 2'b10;
|
||||
localparam c_DAT_block = 2'b11;
|
||||
|
||||
// Instructions mnemonics based on index (opcode(5 downto 0))
|
||||
localparam logic [45:40] c_Go_Idle_State = 6'd0; //CMD0
|
||||
localparam logic [45:40] c_All_Send_CID = 6'd02; // CMD2
|
||||
localparam logic [45:40] c_SD_Send_RCA = 6'd03; // CMD3
|
||||
localparam logic [45:40] c_Switch_Function = 6'd06; // CMD6
|
||||
localparam logic [45:40] c_Set_Bus_Width = 6'd06; // ACMD6
|
||||
localparam logic [45:40] c_Select_Card = 6'd07; // CMD7
|
||||
localparam logic [45:40] c_Send_IF_State = 6'd08; // CMD8
|
||||
localparam logic [45:40] c_Read_Single_Block = 6'd17; // CMD17
|
||||
localparam logic [45:40] c_SD_Send_OCR = 6'd41; // ACMD41
|
||||
localparam logic [45:40] c_App_Command = 6'd55; // CMD55
|
||||
|
||||
// clock selection
|
||||
localparam c_sd_clk_init = 1'b1;
|
||||
localparam c_sd_clk_hs = 1'b0;
|
||||
|
||||
//tx source selection
|
||||
localparam logic [1:0] c_tx_low = 2'b00;
|
||||
localparam logic [1:0] c_tx_high = 2'b01;
|
||||
localparam logic [1:0] c_tx_head = 2'b10;
|
||||
localparam logic [1:0] c_tx_tail = 2'b11;
|
||||
|
||||
// Error Codes for Error Register
|
||||
localparam logic [2:0] c_NO_ERRORS = 3'b000; // no fatal errors occurred
|
||||
// (default value when register is cleared during reset)
|
||||
localparam [2:0] C_ERROR_NO_CMD_RESPONSE = 3'b100; // card timed out while waiting for a response on CMD, no start bit
|
||||
// of response packet was ever received
|
||||
// (possible causes: illegal command, card is disconnected,
|
||||
// not meeting timing (you can fix timing by inverting the clock
|
||||
// sent to card))
|
||||
localparam logic [2:0] c_ERROR_NO_DAT_RESPONSE = 3'b101; // card timed out while waiting for a data block on DAT, no start bit
|
||||
// of DAT packet was ever received
|
||||
// (possible cause: card is disconnected)
|
||||
localparam logic [2:0] C_ERROR_BAD_CARD_STATUS = 3'b110; // status bits of a response indicate a card is not supported
|
||||
// or that the card is damaged internally
|
||||
localparam logic [2:0] C_ERROR_EXCEED_MAX_ATTEMPTS = 3'b111; // if a command fails it may be resent,
|
||||
// but after so many attempts you should just give up
|
||||
|
||||
//Alias for value of SD_CMD_Output_Enable
|
||||
localparam c_TX_COMMAND = 1'b1; // Enable output on SD_CMD
|
||||
localparam c_RX_RESPONSE = 1'b0; // Disable Output on SD_CMD
|
||||
|
||||
// load values in for timers and counters
|
||||
localparam logic [7:0] c_NID_max = 8'd63; // counter_in: should be "4"
|
||||
// downto 0 = 5 bits count
|
||||
// but is not enough time for
|
||||
// sdModel.v
|
||||
localparam logic [7:0] c_NCR_max = 8'd63; // counter_in
|
||||
localparam logic [7:0] c_NCC_min = 8'd7; // counter_in
|
||||
localparam logic [7:0] c_NRC_min = 8'd8; // counter_in
|
||||
|
||||
localparam logic [18:0] c_1000ms = 18'd400000; // ACMD41 timeout
|
||||
|
||||
// command instruction type (opcode(6))
|
||||
localparam c_CMD = 1'b0;
|
||||
localparam c_ACMD = 1'b1;
|
||||
|
||||
// counter direction for up_down
|
||||
localparam c_increment = 1'b1; // count <= count + 1
|
||||
localparam c_decrement = 1'b0; // count <= count - 1
|
||||
|
||||
assign Timer_In = LIMIT_SD_TIMERS ? 19'b0000000000000000011 : 19'b0011000011010100000; // 250 ms
|
||||
|
||||
//Fail Counter, tracks how many failed attempts at command transmission
|
||||
counter #(11) fail_counter
|
||||
(.CountIn(11'b0),
|
||||
.CountOut(r_fail_count_out),
|
||||
.Load(1'b0),
|
||||
.Enable(w_fail_cnt_en),
|
||||
.clk(CLK),
|
||||
.reset(w_fail_count_rst));
|
||||
|
||||
// Simple timer for ACMD41 busy
|
||||
simple_timer #(19) ACMD41_busy_timer
|
||||
(.VALUE(c_1000ms),
|
||||
.START(w_ACMD41_busy_timer_START),
|
||||
.FLAG(w_ACMD41_times_out_FLAG),
|
||||
.RST(w_ACMD41_busy_timer_RST),
|
||||
.CLK(CLK));
|
||||
|
||||
// State Register, instantiate register_ce. 32 state state machine
|
||||
flopenr #(5) state_reg
|
||||
(.d(w_next_state),
|
||||
.q(r_curr_state),
|
||||
.en(1'b1),
|
||||
.reset(i_RST),
|
||||
.clk(CLK));
|
||||
|
||||
// Error register : indicates what type of fatal error occured for interrupt
|
||||
flopenr #(3) error_reg
|
||||
(.d(w_ERROR_CODE_D),
|
||||
.q(r_ERROR_CODE_Q),
|
||||
.en(w_ERROR_CODE_EN),
|
||||
.reset(w_ERROR_CODE_RST),
|
||||
.clk(CLK));
|
||||
|
||||
assign o_ERROR_CODE_Q = r_ERROR_CODE_Q;
|
||||
|
||||
assign w_next_state = i_RST ? s_reset_clear_error_reg :
|
||||
|
||||
((r_curr_state == s_reset_clear_error_reg) |
|
||||
(r_curr_state == s_Error_TX_Failed) |
|
||||
(r_curr_state == s_error_no_response) |
|
||||
(r_curr_state == s_error_bad_card) |
|
||||
(r_curr_state == s_error_dat_time_out)) ? s_reset_from_error :
|
||||
|
||||
|
||||
((r_curr_state == s_reset_from_error) |
|
||||
((r_curr_state == s_idle_supply_no_clk) & (i_TIMER_OUT > 0))) ? s_idle_supply_no_clk :
|
||||
|
||||
(((r_curr_state == s_idle_supply_no_clk) & (i_TIMER_OUT == 0)) |
|
||||
((r_curr_state == s_idle_supply_sd_clk) & (i_COUNTER_OUT > 0))) ? s_idle_supply_sd_clk :
|
||||
|
||||
(r_curr_state == s_ld_head) ? s_count_attempt :
|
||||
|
||||
(((r_curr_state == s_count_attempt) & (r_fail_count_out <= (c_MAX_ATTEMPTS-1))) |
|
||||
((r_curr_state == s_count_attempt) &
|
||||
(((i_IC_OUT == 2) & (i_OPCODE[5:0] == c_App_Command)) |
|
||||
((i_IC_OUT == 3) & (i_OPCODE == ({c_ACMD, c_SD_Send_OCR})))) // to work CMD55, ACMD41 MUST be lines 2, 3 of instruction fetch mux of sd_top.vhd
|
||||
& (w_ACMD41_times_out_FLAG)
|
||||
& (r_fail_count_out > (c_MAX_ATTEMPTS-1)))) ? s_tx_head :
|
||||
|
||||
((r_curr_state == s_count_attempt) & (r_fail_count_out > (c_MAX_ATTEMPTS-1))) ? s_Error_TX_Failed :
|
||||
|
||||
((r_curr_state == s_tx_head) | ((r_curr_state == s_ld_tail) & (i_COUNTER_OUT > 8))) ? s_ld_tail :
|
||||
|
||||
(((r_curr_state == s_ld_tail) & (i_COUNTER_OUT == 8)) |
|
||||
((r_curr_state == s_tx_tail) & (i_COUNTER_OUT > 0))) ? s_tx_tail :
|
||||
|
||||
(r_curr_state == s_tx_tail) & (i_COUNTER_OUT == 0) ? s_setup_rx :
|
||||
|
||||
(((r_curr_state == s_setup_rx) & (i_R_TYPE == c_response_type_R0_NONE)) |
|
||||
((r_curr_state == s_idle_ncc) & (i_COUNTER_OUT > 0))) ? s_idle_ncc :
|
||||
|
||||
(((r_curr_state == s_setup_rx) & (i_R_TYPE != c_response_type_R0_NONE)) |
|
||||
((r_curr_state == s_idle_for_start_bit) & (i_SD_CMD_RX != c_start_bit) &
|
||||
(i_COUNTER_OUT > 0))) ? s_idle_for_start_bit :
|
||||
|
||||
((r_curr_state == s_idle_for_start_bit) & (i_SD_CMD_RX != c_start_bit) &
|
||||
(i_COUNTER_OUT == 0)) ? s_error_no_response :
|
||||
|
||||
(((r_curr_state == s_idle_for_start_bit) & (i_SD_CMD_RX == c_start_bit) &
|
||||
(i_COUNTER_OUT >= 0) & (i_R_TYPE == c_response_type_R2_CID_CSD)) |
|
||||
((r_curr_state == s_rx_136) & (i_COUNTER_OUT > 0))) ? s_rx_136 :
|
||||
|
||||
(((r_curr_state == s_idle_for_start_bit) & (i_SD_CMD_RX == c_start_bit) &
|
||||
(i_COUNTER_OUT >= 0) & (i_R_TYPE != c_response_type_R2_CID_CSD)) |
|
||||
((r_curr_state == s_rx_48) & (i_COUNTER_OUT > 0))) ? s_rx_48 :
|
||||
|
||||
(((r_curr_state == s_rx_136) & (i_COUNTER_OUT == 0)) |
|
||||
((r_curr_state == s_rx_48) & (i_COUNTER_OUT) == 0)) ? s_study_response :
|
||||
|
||||
(r_curr_state == s_study_response) & w_bad_card ? s_error_bad_card :
|
||||
|
||||
(((r_curr_state == s_study_response) & (~w_bad_card) & (i_USES_DAT != c_DAT_none)) |
|
||||
((r_curr_state == s_idle_for_dat) & (~i_DAT_RX_DONE))) ? s_idle_for_dat :
|
||||
|
||||
((r_curr_state == s_idle_for_dat) & (i_DAT_RX_DONE) & (i_ERROR_DAT_TIMES_OUT)) ? s_error_dat_time_out :
|
||||
|
||||
(((r_curr_state == s_idle_for_dat) & (i_DAT_RX_DONE) &
|
||||
(~i_ERROR_DAT_TIMES_OUT)) |
|
||||
((r_curr_state == s_study_response) & (~w_bad_card) &
|
||||
(i_USES_DAT == c_DAT_none)) |
|
||||
((r_curr_state == s_idle_nrc) & (i_COUNTER_OUT > 0))) ? s_idle_nrc :
|
||||
|
||||
((r_curr_state == s_idle_nrc) & (i_COUNTER_OUT == 0) &
|
||||
(w_resend_last_command) & ((i_OPCODE[6] == c_ACMD) &
|
||||
((i_OPCODE[5:0]) != c_App_Command))) ? s_fetch_prev_cmd :
|
||||
|
||||
((r_curr_state == s_fetch_prev_cmd) |
|
||||
((r_curr_state == s_idle_supply_sd_clk) & (i_COUNTER_OUT == 0)) |
|
||||
((r_curr_state == s_fetch_next_cmd) & // before CMD17
|
||||
(i_IC_OUT < 9)) | // blindly load head of next command
|
||||
((r_curr_state == s_idle_for_read_request) & (i_READ_REQUEST)) | // got the request, load head
|
||||
((r_curr_state == s_idle_nrc) & (i_COUNTER_OUT == 0) &
|
||||
(w_resend_last_command) & ((i_OPCODE[6] == c_CMD) |
|
||||
((i_OPCODE[5:0]) == c_App_Command)))) ? s_ld_head :
|
||||
|
||||
(((r_curr_state == s_idle_nrc) & (i_COUNTER_OUT == 0) &
|
||||
(~w_resend_last_command) & ((i_OPCODE) == ({c_CMD, c_Switch_Function}))) |
|
||||
((r_curr_state == s_idle_for_clock_change) & (~i_CLOCK_CHANGE_DONE))) ? s_idle_for_clock_change :
|
||||
|
||||
(((r_curr_state == s_idle_ncc) & (i_COUNTER_OUT == 0)) |
|
||||
((r_curr_state == s_idle_nrc) & (i_COUNTER_OUT == 0) &
|
||||
(~w_resend_last_command) & ((i_OPCODE) != ({c_CMD, c_Switch_Function}))) |
|
||||
((r_curr_state == s_idle_for_clock_change) & (i_CLOCK_CHANGE_DONE))) ? s_fetch_next_cmd :
|
||||
|
||||
(((r_curr_state == s_fetch_next_cmd) &
|
||||
(i_IC_OUT >= 9)) | // During and after CMD17, wait for request to send CMD17 from core
|
||||
// waiting for request
|
||||
(r_curr_state == s_idle_for_read_request)) ? s_idle_for_read_request :
|
||||
|
||||
s_reset_clear_error_reg;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// state outputs
|
||||
assign w_ACMD41_busy_timer_START = ((r_curr_state == s_count_attempt) & (i_OPCODE == {c_ACMD, c_SD_Send_OCR}) & (r_fail_count_out == 1));
|
||||
|
||||
assign w_ACMD41_busy_timer_RST = ((r_curr_state == s_reset_from_error) | (w_ACMD41_init_done));
|
||||
|
||||
// Error Register
|
||||
assign w_ERROR_CODE_RST = (r_curr_state == s_reset_clear_error_reg);
|
||||
|
||||
assign w_ERROR_CODE_EN = (r_curr_state == s_error_bad_card) | (r_curr_state == s_error_no_response) | (r_curr_state == s_Error_TX_Failed) | (r_curr_state == s_error_dat_time_out);
|
||||
|
||||
assign w_ERROR_CODE_D = (r_curr_state == s_Error_TX_Failed) ? C_ERROR_EXCEED_MAX_ATTEMPTS : // give up
|
||||
(r_curr_state == s_error_bad_card) ? C_ERROR_BAD_CARD_STATUS : // card is damaged or unsupported
|
||||
(r_curr_state == s_error_no_response) ? C_ERROR_NO_CMD_RESPONSE : // no response was received on CMD line
|
||||
(r_curr_state == s_error_dat_time_out) ? c_ERROR_NO_DAT_RESPONSE : // no data packet was received on DAT bus
|
||||
c_NO_ERRORS; // all is well
|
||||
|
||||
// Failure counter
|
||||
assign w_fail_count_rst = ((r_curr_state == s_reset_from_error) | (r_curr_state == s_fetch_next_cmd & i_OPCODE[5:0] != c_App_Command));
|
||||
|
||||
|
||||
assign w_fail_cnt_en = ((r_curr_state == s_count_attempt) & (i_OPCODE[6] != c_ACMD | i_OPCODE[5:0] == c_App_Command));
|
||||
// & (i_OPCODE != ({c_ACMD, c_SD_Send_OCR})) else // NOT ACMD41, it can take up to 1 second
|
||||
|
||||
// Timer module
|
||||
assign o_TIMER_EN = (r_curr_state == s_idle_supply_no_clk);
|
||||
|
||||
assign o_TIMER_LOAD = (r_curr_state == s_reset_from_error);
|
||||
|
||||
assign o_TIMER_IN = (r_curr_state == s_reset_from_error) ? Timer_In : '0;
|
||||
|
||||
// Clock selection/gater module(s) ...
|
||||
assign o_SD_CLK_EN = ~((r_curr_state == s_reset_from_error) | (r_curr_state == s_idle_supply_no_clk) | (r_curr_state == s_idle_for_clock_change));
|
||||
|
||||
assign o_START_CLOCK_CHANGE = (r_curr_state == s_idle_for_clock_change);
|
||||
|
||||
// RCA register module
|
||||
assign o_RCA_REGISTER_RST = (r_curr_state == s_reset_from_error);
|
||||
|
||||
assign o_RCA_REGISTER_EN = ((r_curr_state == s_idle_nrc) & (i_R_TYPE == c_response_type_R6_RCA));
|
||||
|
||||
// Instruction counter module
|
||||
assign o_IC_RST = (r_curr_state == s_reset_from_error);
|
||||
|
||||
//assign o_IC_EN = (r_curr_state == s_fetch_next_cmd) | (r_curr_state == s_fetch_prev_cmd);
|
||||
|
||||
assign o_IC_EN = (((r_curr_state == s_fetch_next_cmd) & (i_IC_OUT < 10)) | (r_curr_state == s_fetch_prev_cmd));
|
||||
|
||||
assign o_IC_UP_DOWN = (r_curr_state == s_fetch_prev_cmd) ? c_decrement : c_increment;
|
||||
|
||||
// "Previous Command sent was CMD55, so the command I'm now sending is ACMD" module
|
||||
assign o_CMD_TX_IS_CMD55_RST = (r_curr_state == s_reset_from_error);
|
||||
|
||||
assign o_CMD_TX_IS_CMD55_EN = (r_curr_state == s_ld_head);
|
||||
|
||||
// Output signals to DAT FSM
|
||||
//o_CMD_TX_DONE = '0' when (r_curr_state == s_reset) else // reset
|
||||
// '0' when (r_curr_state == s_idle_supply_no_clk) | (r_curr_state == s_idle_supply_sd_clk) else // power up
|
||||
// '0' when ((r_curr_state == s_ld_head)
|
||||
// | (r_curr_state == s_tx_head)
|
||||
// | (r_curr_state == s_ld_tail)
|
||||
// | (r_curr_state == s_tx_tail)) else // tx
|
||||
// '1';
|
||||
assign o_CMD_TX_DONE = (r_curr_state == s_setup_rx);
|
||||
|
||||
// Counter Module
|
||||
assign o_COUNTER_LOAD = (r_curr_state == s_idle_supply_no_clk) |
|
||||
(r_curr_state == s_ld_head) |
|
||||
(r_curr_state == s_setup_rx) |
|
||||
(r_curr_state == s_idle_for_start_bit) & (i_SD_CMD_RX == c_start_bit) |
|
||||
(r_curr_state == s_rx_48) & (i_COUNTER_OUT == 0) |
|
||||
(r_curr_state == s_rx_136) & (i_COUNTER_OUT == 0);
|
||||
|
||||
assign o_COUNTER_IN = (r_curr_state == s_idle_supply_no_clk) ? 8'd73 :
|
||||
// | is it 73 downto 0 == 74 bits
|
||||
(r_curr_state == s_ld_head) ? 8'd47 : // or is it 48
|
||||
((r_curr_state == s_setup_rx) & (i_R_TYPE == c_response_type_R0_NONE)) ? c_NCC_min :
|
||||
((r_curr_state == s_setup_rx)
|
||||
& (i_R_TYPE != c_response_type_R0_NONE)
|
||||
& (((i_OPCODE) == ({c_CMD, c_All_Send_CID})) |
|
||||
((i_OPCODE) == ({c_ACMD, c_SD_Send_OCR})))) ? c_NID_max :
|
||||
(r_curr_state == s_setup_rx) ? c_NCR_max :
|
||||
((r_curr_state == s_idle_for_start_bit) & (i_R_TYPE == c_response_type_R2_CID_CSD)) ? 8'd135 : // | is it 136
|
||||
(r_curr_state == s_idle_for_start_bit) ? 8'd46 : // | is it not48
|
||||
(r_curr_state == s_rx_48) | (r_curr_state == s_rx_136) ? c_NRC_min : // | is it 8
|
||||
8'd0;
|
||||
|
||||
assign o_COUNTER_EN = (r_curr_state == s_idle_supply_sd_clk) ? 1'b1 :
|
||||
((r_curr_state == s_tx_head) | (r_curr_state == s_ld_tail) | (r_curr_state == s_tx_tail)) ? 1'b1 :
|
||||
(r_curr_state == s_idle_for_start_bit) & (i_SD_CMD_RX == c_start_bit) ? 1'b0 :
|
||||
(r_curr_state == s_idle_for_start_bit) ? 1'b1 :
|
||||
(r_curr_state == s_rx_48) & (i_COUNTER_OUT == 0) ? 1'b0 :
|
||||
(r_curr_state == s_rx_48) ? 1'b1 :
|
||||
(r_curr_state == s_idle_nrc) ? 1'b1 :
|
||||
(r_curr_state == s_rx_136) & (i_COUNTER_OUT == 0) ? 1'b0 :
|
||||
(r_curr_state == s_rx_136) ? 1'b1 :
|
||||
(r_curr_state == s_idle_ncc) ? 1'b1 :
|
||||
1'b0;
|
||||
|
||||
// SD_CMD Tri-state Buffer Module
|
||||
assign o_SD_CMD_OE = (r_curr_state == s_idle_supply_sd_clk) ? c_TX_COMMAND :
|
||||
((r_curr_state == s_tx_head)
|
||||
| (r_curr_state == s_ld_tail)
|
||||
| (r_curr_state == s_tx_tail)) ? c_TX_COMMAND :
|
||||
c_RX_RESPONSE;
|
||||
|
||||
// Shift Registers
|
||||
// TX_PISO40 Transmit Command Head
|
||||
assign o_TX_PISO40_LOAD = (r_curr_state == s_ld_head);
|
||||
|
||||
assign o_TX_PISO40_EN = (r_curr_state == s_tx_head) | (r_curr_state == s_ld_tail);
|
||||
|
||||
// TX_CRC7_PIPO Generate Tail
|
||||
assign o_TX_CRC7_PIPO_RST = (r_curr_state == s_ld_head);
|
||||
|
||||
assign o_TX_CRC7_PIPO_EN = (r_curr_state == s_tx_head);
|
||||
|
||||
// TX_PISO8 Transmit Command Tail
|
||||
assign o_TX_PISO8_LOAD = (r_curr_state == s_ld_tail);
|
||||
|
||||
assign o_TX_PISO8_EN = (r_curr_state == s_tx_tail);
|
||||
|
||||
// RX_CRC7_SIPO Calculate the CRC7 of the first 47-bits of reply (should be zero)
|
||||
assign o_RX_CRC7_SIPO_RST = (r_curr_state == s_setup_rx);
|
||||
|
||||
assign o_RX_CRC7_SIPO_EN = (r_curr_state == s_rx_48) & (i_COUNTER_OUT > 0); // or (r_curr_state == s_rx_48_b)
|
||||
|
||||
// RX_SIPO40 Content bits of response
|
||||
assign o_RX_SIPO48_RST = (r_curr_state == s_setup_rx);
|
||||
|
||||
assign o_RX_SIPO48_EN = (r_curr_state == s_rx_48 | r_curr_state == s_rx_48);
|
||||
|
||||
// Fatal Error Signal Wire
|
||||
assign o_FATAL_ERROR = (r_curr_state == s_error_bad_card) | (r_curr_state == s_error_no_response) |
|
||||
(r_curr_state == s_Error_TX_Failed) | (r_curr_state == s_error_dat_time_out);
|
||||
|
||||
assign o_DAT_ERROR_FD_RST = (r_curr_state == s_ld_head);
|
||||
|
||||
// I'm debating the merit of creating yet another state for sd_cmd_fsm.vhd to go into when and if sd_dat_fsm.vhd
|
||||
// times out while waiting for start bit on the DAT bus resulting in Error_Time_Out going high in
|
||||
// sd_Dat_fsm.vhd while sd_cmd_fsm.vhd is still in s_idle_for_dat
|
||||
|
||||
// TX source selection bits for mux
|
||||
assign o_TX_SOURCE_SELECT = (r_curr_state == s_idle_supply_sd_clk) ? c_tx_high :
|
||||
((r_curr_state == s_ld_head)
|
||||
| (r_curr_state == s_tx_head)
|
||||
| (r_curr_state == s_ld_tail)) ? c_tx_head :
|
||||
(r_curr_state == s_tx_tail) ? c_tx_tail :
|
||||
c_tx_high; // This occurs when not transmitting anything
|
||||
|
||||
// Study Response
|
||||
assign w_rx_crc7_check = (r_curr_state == s_idle_nrc) &
|
||||
((i_R_TYPE != c_response_type_R0_NONE) &
|
||||
(i_R_TYPE != c_response_type_R3_OCR) &
|
||||
(i_R_TYPE != c_response_type_R2_CID_CSD));
|
||||
|
||||
assign w_rx_index_check = (r_curr_state == s_idle_nrc) &
|
||||
((i_R_TYPE != c_response_type_R0_NONE) &
|
||||
(i_R_TYPE != c_response_type_R3_OCR) &
|
||||
(i_R_TYPE != c_response_type_R2_CID_CSD));
|
||||
|
||||
assign w_redo_result = i_RESPONSE_CONTENT & i_NO_REDO_MASK;
|
||||
|
||||
assign w_rx_bad_reply = ((r_curr_state == s_idle_nrc | r_curr_state == s_study_response) & (w_redo_result != i_NO_REDO_ANS));
|
||||
|
||||
assign w_rx_bad_crc7 = ((r_curr_state == s_idle_nrc | r_curr_state == s_study_response) & ((w_rx_crc7_check) & (i_RX_CRC7 != 7'b0)));
|
||||
|
||||
assign w_rx_bad_index = ((r_curr_state == s_idle_nrc | r_curr_state == s_study_response)
|
||||
& ((w_rx_index_check) & (i_RESPONSE_INDEX != i_OPCODE[5:0])));
|
||||
|
||||
assign w_resend_last_command = ((r_curr_state == s_idle_nrc | r_curr_state == s_study_response) &
|
||||
((w_rx_bad_reply) | (w_rx_bad_index) | (w_rx_bad_crc7))) |
|
||||
((r_curr_state == s_idle_nrc) &
|
||||
((i_ERROR_CRC16) &
|
||||
((i_USES_DAT == c_DAT_block) | (i_USES_DAT == c_DAT_wide))));
|
||||
|
||||
assign w_error_result = i_RESPONSE_CONTENT & i_NO_ERROR_MASK;
|
||||
|
||||
// Make assignment based on what was read from the OCR Register.
|
||||
// Bit 31, Card power up status bit: '1' == SD Flash Card power up procedure is finished.
|
||||
// '0' == SD Flash Card power up procedure is not finished.
|
||||
// Bit 30, Card capacity status bit: '1' == Extended capacity card is in use (64 GB in size or greater).
|
||||
// '0' == Extended capacity card is not in use.
|
||||
assign w_ACMD41_init_done = ((i_IC_OUT == 3) & (i_OPCODE == ({c_ACMD, c_SD_Send_OCR}))) &
|
||||
(~w_rx_bad_reply) & (r_curr_state == s_study_response);
|
||||
|
||||
assign w_bad_card = ((r_curr_state == s_study_response) & (w_error_result != i_NO_ERROR_ANS) &
|
||||
((~w_ACMD41_times_out_FLAG) | (w_ACMD41_init_done)));
|
||||
|
||||
// Communication with core
|
||||
assign o_READY_FOR_READ = (r_curr_state == s_idle_for_read_request);
|
||||
|
||||
assign o_SD_RESTARTING = (r_curr_state == s_Error_TX_Failed) |
|
||||
(r_curr_state == s_error_dat_time_out) |
|
||||
(r_curr_state == s_error_bad_card) |
|
||||
(r_curr_state == s_error_no_response);
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
233
wally-pipelined/src/sdc/sd_dat_fsm.sv
Normal file
233
wally-pipelined/src/sdc/sd_dat_fsm.sv
Normal file
@ -0,0 +1,233 @@
|
||||
///////////////////////////////////////////
|
||||
// sd_dat_fsm.sv
|
||||
//
|
||||
// Written: Ross Thompson September 19, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Runs in parallel with sd_cmd_fsm to control activity on the DAT
|
||||
// bus of the SD card.
|
||||
// 14 State Mealy FSM + Safe state = 15 State Mealy FSM
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module sd_dat_fsm
|
||||
(
|
||||
input logic CLK, // HS Clock (48 MHz)
|
||||
input logic i_RST,
|
||||
// Timer module control
|
||||
input logic i_SD_CLK_SELECTED, // Which frequency I'm in determines what count in to load for a 100ms timer
|
||||
output logic o_TIMER_LOAD, o_TIMER_EN, // Timer Control signals
|
||||
output logic [22:0] o_TIMER_IN, // Need Enough bits for 100 milliseconds at 48MHz
|
||||
input logic [22:0] i_TIMER_OUT, // (ceiling(log((clk freq)(delay desired)-1)/log(2))-1) downto 0
|
||||
// Nibble counter module control
|
||||
output logic o_COUNTER_RST, o_COUNTER_EN, // nibble counter
|
||||
input logic [10:0] i_COUNTER_OUT, // max nibbles is 1024 + crc16 bits = 1040 bits
|
||||
// CRC16 Generation control
|
||||
output logic o_CRC16_EN, o_CRC16_RST, // shared signals for all 4 CRC16_SIPO (one for each of 4 DAT lines)
|
||||
input logic i_DATA_CRC16_GOOD, // indicates that no errors in transmission when CRC16 are all zero
|
||||
// For R1b
|
||||
output logic o_BUSY_RST, o_BUSY_EN, // busy signal for R1b
|
||||
input logic i_DAT0_Q,
|
||||
// Storage Buffers for DAT bits read
|
||||
output logic o_NIBO_EN, // 512 bytes block data (Nibble In Block Out)
|
||||
// From LUT
|
||||
input logic [1:0] i_USES_DAT, // current command needs use of DAT bus
|
||||
// For communicating with core
|
||||
output logic o_DATA_VALID, // indicates that DATA being send over o_DATA to core is valid
|
||||
output logic o_LAST_NIBBLE, // indicates that the last nibble has been sent
|
||||
// For communication with sd_cmd_fsm
|
||||
input logic i_CMD_TX_DONE, // command transmission completed, begin waiting for DATA
|
||||
output logic o_DAT_RX_DONE, // tell SD_CMD_FSM that DAT communication is completed, send next instruction to sd card
|
||||
output logic o_ERROR_DAT_TIMES_OUT, // error flag for when DAT times out (so don't fetch more instructions)
|
||||
output logic o_DAT_ERROR_FD_RST,
|
||||
output logic o_DAT_ERROR_FD_EN, // tell SD_CMD_FSM to resend command due to error in transmission
|
||||
input logic LIMIT_SD_TIMERS
|
||||
);
|
||||
|
||||
logic [3:0] w_next_state, r_curr_state;
|
||||
|
||||
logic w_error_crc16_fd_en, w_error_crc16_fd_rst, w_error_crc16_fd_d; // Save ERROR_CRC16 so CMD FSM sees it in IDLE_NRC (not just in IDLE_DAT)
|
||||
logic r_error_crc16_fd_Q;
|
||||
|
||||
logic [22:0] Identify_Timer_In;
|
||||
logic [22:0] Data_TX_Timer_In;
|
||||
|
||||
localparam logic [3:0] s_reset = 4'b0000;
|
||||
localparam logic [3:0] s_idle = 4'b0001;
|
||||
localparam logic [3:0] s_idle_for_start_bit = 4'b0010;
|
||||
localparam logic [3:0] s_read_r1b = 4'b0011;
|
||||
localparam logic [3:0] s_notify_r1b_completed = 4'b0100;
|
||||
localparam logic [3:0] s_error_time_out = 4'b0101;
|
||||
localparam logic [3:0] s_rx_wide_data = 4'b0110;
|
||||
localparam logic [3:0] s_rx_block_data = 4'b0111;
|
||||
localparam logic [3:0] s_rx_crc16 = 4'b1000;
|
||||
localparam logic [3:0] s_error_crc16_fail = 4'b1001;
|
||||
localparam logic [3:0] s_publish_block_data = 4'b1010;
|
||||
localparam logic [3:0] s_publish_wide_data = 4'b1011;
|
||||
localparam logic [3:0] s_reset_wide_data = 4'b1100;
|
||||
localparam logic [3:0] s_reset_block_data = 4'b1101;
|
||||
localparam logic [3:0] s_reset_nibble_counter = 4'b1110; // Before publishing CMD17 Block Data
|
||||
|
||||
localparam logic [1:0] c_DAT_none = 2'b00;
|
||||
localparam logic [1:0] c_DAT_busy = 2'b01;
|
||||
localparam logic [1:0] c_DAT_wide = 2'b10;
|
||||
localparam logic [1:0] c_DAT_block = 2'b11;
|
||||
|
||||
localparam logic c_start_bit = 0;
|
||||
localparam logic c_busy_bit = 0;
|
||||
|
||||
// load values in for timers and counters
|
||||
localparam logic c_slow_clock = 1'b1; // use during initialization (card identification mode)
|
||||
localparam logic c_HS_clock = 1'b0; // use after CMD6 switches clock frequency (CMD17)
|
||||
|
||||
|
||||
assign Identify_Timer_In = LIMIT_SD_TIMERS ? 23'b00000000000000001100011 : 23'b00000001001110001000000; // 40,000 unsigned.
|
||||
assign Data_TX_Timer_In = LIMIT_SD_TIMERS ? 23'b00000000000000001100011 : 23'b11110100001001000000000; // 8,000,000 unsigned.
|
||||
|
||||
flopenr #(4) stateReg(.clk(CLK),
|
||||
.reset(i_RST),
|
||||
.en(1'b1),
|
||||
.d(w_next_state),
|
||||
.q(r_curr_state));
|
||||
|
||||
assign w_next_state = ((i_RST) |
|
||||
(r_curr_state == s_error_time_out) | // noticed this change is needed during emulation
|
||||
(r_curr_state == s_notify_r1b_completed) |
|
||||
(r_curr_state == s_error_crc16_fail) |
|
||||
(r_curr_state == s_publish_wide_data) |
|
||||
((r_curr_state == s_publish_block_data) & (i_COUNTER_OUT == 1023))) ? s_reset :
|
||||
|
||||
((r_curr_state == s_reset) |
|
||||
((r_curr_state == s_idle) & ((i_USES_DAT == c_DAT_none) | ((i_USES_DAT != c_DAT_none) & (~i_CMD_TX_DONE))))) ? s_idle :
|
||||
|
||||
((r_curr_state == s_idle) & (i_USES_DAT == c_DAT_wide) & (i_CMD_TX_DONE)) ? s_reset_wide_data :
|
||||
|
||||
((r_curr_state == s_idle) & (i_USES_DAT == c_DAT_block) & (i_CMD_TX_DONE)) ? s_reset_block_data :
|
||||
|
||||
((r_curr_state == s_reset_wide_data) |
|
||||
((r_curr_state == s_idle) & (i_USES_DAT == c_DAT_busy) & (i_CMD_TX_DONE)) |
|
||||
(r_curr_state == s_reset_block_data) |
|
||||
((r_curr_state == s_idle_for_start_bit) & (i_TIMER_OUT > 0) & (i_DAT0_Q != c_start_bit))) ? s_idle_for_start_bit :
|
||||
|
||||
((r_curr_state == s_idle_for_start_bit) & // Apparently R1b's busy signal is optional,
|
||||
(i_TIMER_OUT == 0) & // Even if it never shows up,
|
||||
(i_USES_DAT == c_DAT_busy)) ? s_notify_r1b_completed : // pretend it did, & move on
|
||||
|
||||
(((r_curr_state == s_idle_for_start_bit) & (i_TIMER_OUT > 0) &
|
||||
(i_DAT0_Q == c_start_bit) & (i_USES_DAT == c_DAT_busy)) |
|
||||
((r_curr_state == s_read_r1b) & (i_TIMER_OUT > 0) & (i_DAT0_Q == c_busy_bit))) ? s_read_r1b :
|
||||
|
||||
(((r_curr_state == s_read_r1b) & (i_TIMER_OUT == 0)) |
|
||||
((r_curr_state == s_idle_for_start_bit) & (i_TIMER_OUT == 0) &
|
||||
(i_USES_DAT != c_DAT_busy))) ? s_error_time_out :
|
||||
|
||||
((r_curr_state == s_read_r1b) & (i_DAT0_Q != c_busy_bit)) ? s_notify_r1b_completed :
|
||||
|
||||
(((r_curr_state == s_idle_for_start_bit) & (i_TIMER_OUT > 0) & (i_DAT0_Q == c_start_bit) &
|
||||
(i_USES_DAT == c_DAT_wide)) |
|
||||
((r_curr_state == s_rx_wide_data) & (i_COUNTER_OUT < 128))) ? s_rx_wide_data :
|
||||
|
||||
(((r_curr_state == s_idle_for_start_bit) & (i_TIMER_OUT > 0) &
|
||||
(i_DAT0_Q == c_start_bit) & (i_USES_DAT == c_DAT_block)) |
|
||||
((r_curr_state == s_rx_block_data) & (i_COUNTER_OUT < 1023))) ? s_rx_block_data :
|
||||
|
||||
(((r_curr_state == s_rx_wide_data) & (i_COUNTER_OUT == 128)) |
|
||||
((r_curr_state == s_rx_block_data) & (i_COUNTER_OUT == 1023)) |
|
||||
((r_curr_state == s_rx_crc16) &
|
||||
(((i_USES_DAT == c_DAT_wide) & (i_COUNTER_OUT < 144)) |
|
||||
((i_USES_DAT == c_DAT_block) & (i_COUNTER_OUT < 1040))))) ? s_rx_crc16 :
|
||||
|
||||
((r_curr_state == s_rx_crc16) &
|
||||
(((i_USES_DAT == c_DAT_wide) & (i_COUNTER_OUT == 144)) |
|
||||
((i_USES_DAT == c_DAT_block) & (i_COUNTER_OUT == 1040))) &
|
||||
(~i_DATA_CRC16_GOOD)) ? s_error_crc16_fail :
|
||||
|
||||
((r_curr_state == s_rx_crc16) & (i_USES_DAT == c_DAT_wide) & (i_COUNTER_OUT == 144) &
|
||||
(i_DATA_CRC16_GOOD)) ? s_publish_wide_data :
|
||||
|
||||
((r_curr_state == s_rx_crc16) &
|
||||
(i_USES_DAT == c_DAT_block) & (i_COUNTER_OUT == 1040) & (i_DATA_CRC16_GOOD)) ? s_reset_nibble_counter :
|
||||
|
||||
((r_curr_state == s_reset_nibble_counter) |
|
||||
((r_curr_state == s_publish_block_data) & (i_COUNTER_OUT < 1023))) ? s_publish_block_data :
|
||||
|
||||
s_reset;
|
||||
|
||||
assign o_TIMER_IN = (r_curr_state == s_reset) & (i_SD_CLK_SELECTED == c_slow_clock) ? Identify_Timer_In : Data_TX_Timer_In;
|
||||
|
||||
assign o_TIMER_LOAD = ((r_curr_state == s_reset) |
|
||||
(r_curr_state == s_reset_block_data));
|
||||
|
||||
assign o_TIMER_EN = ((r_curr_state == s_idle_for_start_bit) |
|
||||
(r_curr_state == s_read_r1b));
|
||||
|
||||
// Nibble Counter module
|
||||
assign o_COUNTER_RST = (r_curr_state == s_reset) | (r_curr_state == s_reset_nibble_counter);
|
||||
|
||||
assign o_COUNTER_EN = ((r_curr_state == s_rx_block_data) |
|
||||
(r_curr_state == s_rx_wide_data) |
|
||||
(r_curr_state == s_rx_crc16)) | (r_curr_state == s_publish_block_data);
|
||||
|
||||
// CRC16 Generation module
|
||||
assign o_CRC16_RST = (r_curr_state == s_reset);
|
||||
|
||||
assign o_CRC16_EN = ((r_curr_state == s_rx_block_data) |
|
||||
(r_curr_state == s_rx_wide_data) |
|
||||
(r_curr_state == s_rx_crc16));
|
||||
|
||||
// Flip Flop Module (for R1b)
|
||||
assign o_BUSY_RST = (r_curr_state == s_reset);
|
||||
|
||||
//o_BUSY_EN = '1' when ((r_curr_state == s_idle_for_start_bit) |
|
||||
// (r_curr_state == s_read_r1b)) else
|
||||
// '0';
|
||||
assign o_BUSY_EN = 1'b1; // Always sample data
|
||||
|
||||
// DAT Storage Modules
|
||||
assign o_NIBO_EN = (r_curr_state == s_rx_block_data);
|
||||
|
||||
// To sd_cmd_fsm
|
||||
assign o_DAT_RX_DONE = ((r_curr_state == s_error_time_out) |
|
||||
(r_curr_state == s_notify_r1b_completed) |
|
||||
(r_curr_state == s_error_crc16_fail) |
|
||||
(r_curr_state == s_publish_wide_data) |
|
||||
(r_curr_state == s_publish_block_data));
|
||||
|
||||
assign o_ERROR_DAT_TIMES_OUT = (r_curr_state == s_error_time_out);
|
||||
|
||||
|
||||
// o_RESEND_READ_WIDE (Error! This is not defined. Indicates switch command must be re-rent),
|
||||
// should be a function of block busy logic
|
||||
|
||||
// For Communication with core
|
||||
assign o_DATA_VALID = (r_curr_state == s_publish_block_data);
|
||||
|
||||
assign o_LAST_NIBBLE = ((r_curr_state == s_publish_block_data)
|
||||
& (i_COUNTER_OUT == 1023)) | (r_curr_state == s_error_time_out); // notify done if errors occur
|
||||
|
||||
// o_ERROR_CRC16 (note: saved to flip flop because otherwise is only 1 clock cycle, not what I want)
|
||||
assign o_DAT_ERROR_FD_RST = (r_curr_state == s_reset_block_data) | (r_curr_state == s_reset_wide_data);
|
||||
assign o_DAT_ERROR_FD_EN = (r_curr_state == s_rx_crc16);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
665
wally-pipelined/src/sdc/sd_top.sv
Normal file
665
wally-pipelined/src/sdc/sd_top.sv
Normal file
@ -0,0 +1,665 @@
|
||||
///////////////////////////////////////////
|
||||
// sd_top.sv
|
||||
//
|
||||
// Written: Ross Thompson September 19, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: SD card controller
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module sd_top #(parameter g_COUNT_WIDTH = 8)
|
||||
(
|
||||
input logic CLK, // 1.2 GHz (1.0 GHz typical)
|
||||
input logic a_RST, // Reset signal (Must be held for minimum of 24 clock cycles)
|
||||
// a_RST MUST COME OUT OF RESET SYNCHRONIZED TO THE 1.2 GHZ CLOCK!
|
||||
// io_SD_CMD_z : inout std_logic; // SD CMD Bus
|
||||
input logic i_SD_CMD, // CMD Response from card
|
||||
output logic o_SD_CMD, // CMD Command from host
|
||||
output logic o_SD_CMD_OE, // Direction of SD_CMD
|
||||
input logic [3:0] i_SD_DAT, // SD DAT Bus
|
||||
output logic o_SD_CLK, // SD CLK Bus
|
||||
// For communication with core cpu
|
||||
input logic [32:9] i_BLOCK_ADDR, // see "Addressing" in parts.fods (only 8GB total capacity is used)
|
||||
output logic o_READY_FOR_READ, // tells core that initialization sequence is completed and
|
||||
// sd card is ready to read a 512 byte block to the core.
|
||||
// Held high during idle until i_READ_REQUEST is received
|
||||
output logic o_SD_RESTARTING, // inform core the need to restart
|
||||
|
||||
input logic i_READ_REQUEST, // After Ready for read is sent to the core, the core will
|
||||
// pulse this bit high to indicate it wants the block at this address
|
||||
output logic [3:0] o_DATA_TO_CORE, // nibble being sent to core when DATA block is
|
||||
// being published
|
||||
output logic o_DATA_VALID, // held high while data being read to core to indicate that it is valid
|
||||
output logic o_LAST_NIBBLE, // pulse when last nibble is sent
|
||||
output logic [2:0] o_ERROR_CODE_Q, // indicates which error occured
|
||||
output logic o_FATAL_ERROR, // indicates that the FATAL ERROR register has updated
|
||||
// For tuning
|
||||
input logic [g_COUNT_WIDTH-1:0] i_COUNT_IN_MAX,
|
||||
input logic LIMIT_SD_TIMERS
|
||||
);
|
||||
|
||||
localparam logic c_CMD = 1'b0;
|
||||
localparam logic c_ACMD = 1'b1;
|
||||
|
||||
// packet bit names
|
||||
localparam logic c_start_bit = 1'b0; // bit 47
|
||||
localparam logic c_stop_bit = 1'b1; // bit 0, AKA "end bit"
|
||||
// transmitter bit, bit 46
|
||||
localparam logic c_tx_host_command = 1'b1;
|
||||
localparam logic c_tx_card_response = 1'b0;
|
||||
|
||||
// response types
|
||||
localparam logic [2:0] c_response_type_R0_NONE = 3'd0;
|
||||
localparam logic [2:0] c_response_type_R1_NORMAL = 3'd1;
|
||||
localparam logic [2:0] c_response_type_R2_CID_CSD = 3'd2;
|
||||
localparam logic [2:0] c_response_type_R3_OCR = 3'd3;
|
||||
localparam logic [2:0] c_response_type_R6_RCA = 3'd6;
|
||||
localparam logic [2:0] c_response_type_R7_CIC = 3'd7;
|
||||
|
||||
// uses dat
|
||||
localparam logic [1:0] c_DAT_none = 2'b00;
|
||||
localparam logic [1:0] c_DAT_busy = 2'b01;
|
||||
localparam logic [1:0] c_DAT_wide = 2'b10;
|
||||
localparam logic [1:0] c_DAT_block = 2'b11;
|
||||
|
||||
// tx source selection
|
||||
localparam logic [1:0] c_tx_low = 2'b00;
|
||||
localparam logic [1:0] c_tx_high = 2'b01;
|
||||
localparam logic [1:0] c_tx_head = 2'b10;
|
||||
localparam logic [1:0] c_tx_tail = 2'b11;
|
||||
|
||||
// command indexes
|
||||
localparam logic [45:40] c_Go_Idle_State = 6'd00; // CMD0
|
||||
localparam logic [45:40] c_All_Send_CID = 6'd02; // CMD2
|
||||
localparam logic [45:40] c_SD_Send_RCA = 6'd03; // CMD3
|
||||
localparam logic [45:40] c_Switch_Function = 6'd06; // CMD6
|
||||
localparam logic [45:40] c_Set_Bus_Width = 6'd06; // ACMD6
|
||||
localparam logic [45:40] c_Select_Card = 6'd07; // CMD7
|
||||
localparam logic [45:40] c_Send_IF_State = 6'd08; // CMD8
|
||||
localparam logic [45:40] c_Read_Single_Block = 6'd17; // CMD17
|
||||
localparam logic [45:40] c_SD_Send_OCR = 6'd41; // ACMD41
|
||||
localparam logic [45:40] c_App_Command = 6'd55; // CMD55
|
||||
|
||||
// bitmasks
|
||||
localparam logic [127:96] c_CMD0_mask_check_redo_bits = 32'h00000000; // Go_Idle_State
|
||||
localparam logic [127:96] c_CMD0_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD0_mask_check_error_bits = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD0_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_CMD2_mask_check_redo_bits = 32'h00000000; // All_Send_CID
|
||||
localparam logic [127:96] c_CMD2_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD2_mask_check_error_bits = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD2_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_CMD3_mask_check_redo_bits = 32'h00000000; // SD_Send_RCA
|
||||
localparam logic [127:96] c_CMD3_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD3_mask_check_error_bits = 32'h00002000;
|
||||
localparam logic [127:96] c_CMD3_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_CMD6_mask_check_redo_bits = 32'h00000000; // Switch_Function
|
||||
localparam logic [127:96] c_CMD6_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD6_mask_check_error_bits = 32'h82380000;
|
||||
localparam logic [127:96] c_CMD6_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_ACMD6_mask_check_redo_bits = 32'h00000000; // Set_Bus_Width
|
||||
localparam logic [127:96] c_ACMD6_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_ACMD6_mask_check_error_bits = 32'h8F398020;
|
||||
localparam logic [127:96] c_ACMD6_ans_error_free = 32'h00000020;
|
||||
|
||||
localparam logic [127:96] c_CMD7_mask_check_redo_bits = 32'h00000000; // Select_Card
|
||||
localparam logic [127:96] c_CMD7_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD7_mask_check_error_bits = 32'h0F398000;
|
||||
localparam logic [127:96] c_CMD7_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_CMD8_mask_check_redo_bits = 32'h00000000; // Send_IF_State
|
||||
localparam logic [127:96] c_CMD8_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD8_mask_check_error_bits = 32'h00000FFF;
|
||||
localparam logic [127:96] c_CMD8_ans_error_free = 32'h000001FF;
|
||||
|
||||
localparam logic [127:96] c_CMD17_mask_check_redo_bits = 32'h00000000; // Read_Single_Block
|
||||
localparam logic [127:96] c_CMD17_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD17_mask_check_error_bits = 32'hCF398000;
|
||||
localparam logic [127:96] c_CMD17_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_ACMD41_mask_check_redo_bits = 32'h80000000; // SD_Send_OCR
|
||||
localparam logic [127:96] c_ACMD41_ans_dont_redo = 32'h80000000;
|
||||
localparam logic [127:96] c_ACMD41_mask_check_error_bits = 32'h41FF8000;
|
||||
localparam logic [127:96] c_ACMD41_ans_error_free = 32'h40FF8000;
|
||||
|
||||
localparam logic [127:96] c_CMD55_mask_check_redo_bits = 32'h00000000; // App_Command
|
||||
localparam logic [127:96] c_CMD55_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_CMD55_mask_check_error_bits = 32'h0F398000;
|
||||
localparam logic [127:96] c_CMD55_ans_error_free = 32'h00000000;
|
||||
|
||||
localparam logic [127:96] c_ACMD55_mask_check_redo_bits = 32'h00000000; // App_Command
|
||||
localparam logic [127:96] c_ACMD55_ans_dont_redo = 32'h00000000;
|
||||
localparam logic [127:96] c_ACMD55_mask_check_error_bits = 32'h0F398000;
|
||||
localparam logic [127:96] c_ACMD55_ans_error_free = 32'h00000000;
|
||||
|
||||
// SD_CMD_FSM Connections
|
||||
logic w_TIMER_LOAD, w_TIMER_EN;
|
||||
logic [18:0] w_TIMER_IN;
|
||||
logic [18:0] r_TIMER_OUT;
|
||||
logic w_COUNTER_LOAD, w_COUNTER_EN;
|
||||
logic [7:0] w_COUNTER_IN;
|
||||
logic [7:0] r_COUNTER_OUT;
|
||||
logic w_SD_CLK_EN;
|
||||
logic w_CLOCK_CHANGE_DONE, w_START_CLOCK_CHANGE; // to clk fsm
|
||||
logic w_HS_TO_INIT_CLK_DIVIDER_RST;
|
||||
logic w_IC_RST, w_IC_EN, w_IC_UP_DOWN;
|
||||
//logic w_USES_DAT : std_logic_vector(1 downto 0);
|
||||
//logic w_OPCODE_Q : std_logic_vector(6 downto 0);
|
||||
//logic w_R_TYPE : std_logic_vector(2 downto 0);
|
||||
//logic w_NO_REDO_MASK : std_logic_vector(31 downto 0);
|
||||
//logic w_NO_REDO_ANS : std_logic_vector(31 downto 0);
|
||||
//logic w_NO_ERROR_MASK : std_logic_vector(31 downto 0);
|
||||
//logic w_NO_ERROR_ANS : std_logic_vector(31 downto 0);
|
||||
logic w_SD_CMD_OE;
|
||||
//logic w_SD_CMD_IE : std_logic; // tri-state buffer - input enable (for simulation only)
|
||||
logic w_TX_PISO40_LOAD, w_TX_PISO40_EN;
|
||||
logic w_TX_PISO8_LOAD, w_TX_PISO8_EN;
|
||||
logic w_TX_CRC7_PIPO_RST, w_TX_CRC7_PIPO_EN;
|
||||
logic [1:0] w_TX_SOURCE_SELECT;
|
||||
logic w_CMD_TX_IS_CMD55_RST;
|
||||
logic w_CMD_TX_IS_CMD55_EN;
|
||||
//logic w_CMD_RX;
|
||||
logic w_RX_SIPO48_RST, w_RX_SIPO48_EN;
|
||||
logic [39:8] r_RESPONSE_CONTENT;
|
||||
logic [45:40] r_RESPONSE_INDEX;
|
||||
logic w_RX_CRC7_SIPO_RST, w_RX_CRC7_SIPO_EN;
|
||||
logic [6:0] r_RX_CRC7_Q;
|
||||
logic w_RCA_REGISTER_RST, w_RCA_REGISTER_EN;
|
||||
logic w_CMD_TX_DONE;
|
||||
logic w_DAT_RX_DONE;
|
||||
logic w_DAT_ERROR_FD_RST_DAT, w_DAT_ERROR_FD_RST_CMD, w_DAT_ERROR_FD_RST, w_DAT_ERROR_FD_EN;
|
||||
logic r_DAT_ERROR_Q; // CRC16 error or time out
|
||||
logic w_NOT_DAT_ERROR_Q; // '0'=no error, '1'=tx error on DAT bus
|
||||
logic w_ERROR_DAT_TIMES_OUT;
|
||||
logic w_FATAL_ERROR;
|
||||
logic [2:0] r_ERROR_CODE_Q; // indicates which fatal error occured
|
||||
|
||||
// Communication with core
|
||||
logic w_READY_FOR_READ;
|
||||
logic w_READ_REQUEST;
|
||||
logic [3:0] r_DATA_TO_CORE;
|
||||
logic w_DATA_VALID;
|
||||
logic w_LAST_NIBBLE;
|
||||
|
||||
//SD_DAT_FSM Connections
|
||||
logic w_DAT_TIMER_LOAD, w_DAT_TIMER_EN;
|
||||
logic w_DAT_COUNTER_RST, w_DAT_COUNTER_EN;
|
||||
logic w_CRC16_EN, w_CRC16_RST;
|
||||
logic w_BUSY_RST, w_BUSY_EN;
|
||||
logic w_NIBO_EN;
|
||||
logic w_DATA_CRC16_GOOD;
|
||||
logic w_VALID_BLOCK_D, w_VALID_BLOCK_EN, w_VALID_WIDE_D, w_VALID_WIDE_EN;
|
||||
logic [22:0] w_DAT_TIMER_IN;
|
||||
logic [22:0] r_DAT_TIMER_OUT;
|
||||
logic [10:0] r_DAT_COUNTER_OUT;
|
||||
logic [3:0] r_DAT_Q;
|
||||
|
||||
// RCA Register
|
||||
logic [15:0] w_RCA_D_Q;
|
||||
logic [15:0] r_RCA_Q2;
|
||||
|
||||
// Multiplexer Logics
|
||||
logic [132:0] w_instruction_control_bits;
|
||||
logic [132:130] w_R_TYPE ;
|
||||
logic [129:128] w_USES_DAT ;
|
||||
logic [127:96] w_NO_REDO_MASK ;
|
||||
logic [95:64] w_NO_REDO_ANS ;
|
||||
logic [63:32] w_NO_ERROR_MASK ;
|
||||
logic [31:0] w_NO_ERROR_ANS ;
|
||||
logic [45:40] w_command_index ;
|
||||
logic [39:8] w_command_arguments ;
|
||||
logic [47:8] w_command_head ;
|
||||
logic [6:0] w_OPCODE_Q ;
|
||||
|
||||
// TOP_LEVEL Connections
|
||||
logic [40:9] w_BLOCK_ADDR ;
|
||||
logic [3:0] r_IC_OUT ;
|
||||
logic [2:0] r_command_index_is_55_history ; // [0] is live index, [1] is currently saved index, [2] is index of previous command
|
||||
logic r_previous_command_index_was_55_q; // is index of previous command 55, wired to r_command_index_is_55_history[2]
|
||||
logic r_ACMD_Q; // if the previous command sent to the SD card successfully had index 55, then the SD card thinks the current command is ACMD
|
||||
logic [4095:0] r_block_data ; // data block from CMD17
|
||||
|
||||
// TX
|
||||
logic [45:8] w_command_content; // first 40 bits of command packet
|
||||
logic w_tx_head_Q; // transmission of first part of command packet
|
||||
logic w_tx_tail_Q; // transmission of last part of command packet
|
||||
logic [7:0] r_command_tail; // last 8 bits of command packet
|
||||
logic [6:0] r_TX_CRC7;
|
||||
//logic w_TX_Q:= '0'; // actual transmission when tx is enabled
|
||||
|
||||
// RX
|
||||
logic [47:0] r_RX_RESPONSE;
|
||||
|
||||
// Tri state IO Driver BC18MIMS
|
||||
logic w_SD_CMD_TX_Q; // Write Data
|
||||
logic w_SD_CMD_RX; // Read Data
|
||||
|
||||
|
||||
// CLOCKS
|
||||
//logic r_CLK_HS := '0'; // 50 MHz Divided Clock [static]
|
||||
//logic r_SD_CLK_ungated := '0'; // Selected clock before it is clock gated
|
||||
|
||||
//logic r_SD_CLK := '0'; // GATED CLOCKS
|
||||
logic r_TO_SD_CLK; // What is actually sent to the SD card
|
||||
|
||||
logic w_G_CLK_SD_EN;
|
||||
logic r_CLK_SD, r_G_CLK_SD; // clocks
|
||||
logic r_G_CLK_SD_n;
|
||||
logic [15:0] r_CLK_FSM_RST ; // a_rst logic delayed by one 1.2 GHz period
|
||||
logic w_SD_CLK_SELECTED;
|
||||
|
||||
//DAT FSM Connections
|
||||
logic [15:0] r_DAT3_CRC16, r_DAT2_CRC16, r_DAT1_CRC16;
|
||||
logic [15:0] r_DAT0_CRC16;
|
||||
|
||||
|
||||
assign w_BLOCK_ADDR = {8'h00, i_BLOCK_ADDR}; // (40 downto 36 are zero since card is 64 GB)
|
||||
// (35 downto 32 are zero since memeory is only 8GB total)
|
||||
|
||||
assign o_READY_FOR_READ = w_READY_FOR_READ;
|
||||
assign w_READ_REQUEST = i_READ_REQUEST;
|
||||
assign o_DATA_TO_CORE = r_DATA_TO_CORE;
|
||||
assign o_DATA_VALID = w_DATA_VALID;
|
||||
assign o_LAST_NIBBLE = (w_LAST_NIBBLE | w_FATAL_ERROR); // indicate done if (last nibble OR Fatal Error go high)
|
||||
assign o_FATAL_ERROR = w_FATAL_ERROR;
|
||||
|
||||
sd_cmd_fsm my_sd_cmd_fsm
|
||||
(
|
||||
.CLK(r_G_CLK_SD),
|
||||
.i_RST(a_RST),
|
||||
.o_TIMER_LOAD(w_TIMER_LOAD),
|
||||
.o_TIMER_EN(w_TIMER_EN),
|
||||
.o_TIMER_IN(w_TIMER_IN),
|
||||
.i_TIMER_OUT(r_TIMER_OUT),
|
||||
.o_COUNTER_LOAD(w_COUNTER_LOAD),
|
||||
.o_COUNTER_EN(w_COUNTER_EN),
|
||||
.o_COUNTER_IN(w_COUNTER_IN),
|
||||
.i_COUNTER_OUT(r_COUNTER_OUT),
|
||||
.o_SD_CLK_EN(w_SD_CLK_EN),
|
||||
.i_CLOCK_CHANGE_DONE(w_CLOCK_CHANGE_DONE),
|
||||
.o_START_CLOCK_CHANGE(w_START_CLOCK_CHANGE),
|
||||
.o_IC_RST(w_IC_RST),
|
||||
.o_IC_EN(w_IC_EN),
|
||||
.o_IC_UP_DOWN(w_IC_UP_DOWN),
|
||||
.i_IC_OUT(r_IC_OUT),
|
||||
.i_USES_DAT(w_USES_DAT),
|
||||
.i_OPCODE(w_OPCODE_Q),
|
||||
.i_R_TYPE(w_R_TYPE),
|
||||
.i_NO_REDO_MASK(w_NO_REDO_MASK),
|
||||
.i_NO_REDO_ANS(w_NO_REDO_ANS),
|
||||
.i_NO_ERROR_MASK(w_NO_ERROR_MASK),
|
||||
.i_NO_ERROR_ANS(w_NO_ERROR_ANS),
|
||||
.o_SD_CMD_OE(w_SD_CMD_OE),
|
||||
.o_TX_PISO40_LOAD(w_TX_PISO40_LOAD),
|
||||
.o_TX_PISO40_EN(w_TX_PISO40_EN),
|
||||
.o_TX_PISO8_LOAD(w_TX_PISO8_LOAD),
|
||||
.o_TX_PISO8_EN(w_TX_PISO8_EN),
|
||||
.o_TX_CRC7_PIPO_RST(w_TX_CRC7_PIPO_RST),
|
||||
.o_TX_CRC7_PIPO_EN(w_TX_CRC7_PIPO_EN),
|
||||
.o_TX_SOURCE_SELECT(w_TX_SOURCE_SELECT),
|
||||
.o_CMD_TX_IS_CMD55_RST(w_CMD_TX_IS_CMD55_RST),
|
||||
.o_CMD_TX_IS_CMD55_EN(w_CMD_TX_IS_CMD55_EN),
|
||||
.i_SD_CMD_RX(w_SD_CMD_RX),
|
||||
.o_RX_SIPO48_RST(w_RX_SIPO48_RST),
|
||||
.o_RX_SIPO48_EN(w_RX_SIPO48_EN),
|
||||
.i_RESPONSE_CONTENT(r_RESPONSE_CONTENT),
|
||||
.i_RESPONSE_INDEX(r_RESPONSE_INDEX),
|
||||
.o_RX_CRC7_SIPO_RST(w_RX_CRC7_SIPO_RST),
|
||||
.o_RX_CRC7_SIPO_EN(w_RX_CRC7_SIPO_EN),
|
||||
.i_RX_CRC7(r_RX_CRC7_Q),
|
||||
.o_RCA_REGISTER_RST(w_RCA_REGISTER_RST),
|
||||
.o_RCA_REGISTER_EN(w_RCA_REGISTER_EN),
|
||||
.o_CMD_TX_DONE(w_CMD_TX_DONE),
|
||||
.i_DAT_RX_DONE(w_DAT_RX_DONE),
|
||||
.i_ERROR_CRC16(w_NOT_DAT_ERROR_Q),
|
||||
.i_ERROR_DAT_TIMES_OUT(w_ERROR_DAT_TIMES_OUT),
|
||||
.i_READ_REQUEST(w_READ_REQUEST),
|
||||
.o_READY_FOR_READ(w_READY_FOR_READ),
|
||||
.o_SD_RESTARTING(o_SD_RESTARTING),
|
||||
.o_DAT_ERROR_FD_RST(w_DAT_ERROR_FD_RST_CMD),
|
||||
.o_ERROR_CODE_Q(r_ERROR_CODE_Q),
|
||||
.o_FATAL_ERROR(w_FATAL_ERROR),
|
||||
.LIMIT_SD_TIMERS(LIMIT_SD_TIMERS));
|
||||
|
||||
assign o_ERROR_CODE_Q = r_ERROR_CODE_Q;
|
||||
|
||||
sd_dat_fsm my_sd_dat_fsm
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.i_RST(a_RST),
|
||||
.o_TIMER_LOAD(w_DAT_TIMER_LOAD),
|
||||
.o_TIMER_EN(w_DAT_TIMER_EN),
|
||||
.o_TIMER_IN(w_DAT_TIMER_IN),
|
||||
.i_TIMER_OUT(r_DAT_TIMER_OUT),
|
||||
.i_SD_CLK_SELECTED(w_SD_CLK_SELECTED),
|
||||
.o_COUNTER_RST(w_DAT_COUNTER_RST),
|
||||
.o_COUNTER_EN(w_DAT_COUNTER_EN),
|
||||
.i_COUNTER_OUT(r_DAT_COUNTER_OUT),
|
||||
.o_CRC16_EN(w_CRC16_EN),
|
||||
.o_CRC16_RST(w_CRC16_RST),
|
||||
.i_DATA_CRC16_GOOD(w_DATA_CRC16_GOOD),
|
||||
.o_BUSY_RST(w_BUSY_RST),
|
||||
.o_BUSY_EN(w_BUSY_EN),
|
||||
.i_DAT0_Q(r_DAT_Q[0]),
|
||||
.o_NIBO_EN(w_NIBO_EN),
|
||||
.i_USES_DAT(w_USES_DAT),
|
||||
.i_CMD_TX_DONE(w_CMD_TX_DONE),
|
||||
.o_DAT_RX_DONE(w_DAT_RX_DONE),
|
||||
.o_ERROR_DAT_TIMES_OUT(w_ERROR_DAT_TIMES_OUT),
|
||||
.o_DATA_VALID(w_DATA_VALID),
|
||||
.o_LAST_NIBBLE(w_LAST_NIBBLE),
|
||||
.o_DAT_ERROR_FD_RST(w_DAT_ERROR_FD_RST_DAT),
|
||||
.o_DAT_ERROR_FD_EN(w_DAT_ERROR_FD_EN),
|
||||
.LIMIT_SD_TIMERS(LIMIT_SD_TIMERS));
|
||||
|
||||
assign w_DAT_ERROR_FD_RST = w_DAT_ERROR_FD_RST_CMD | w_DAT_ERROR_FD_RST_DAT;
|
||||
|
||||
flopenr #(1) dat_error_fd
|
||||
(.clk(r_G_CLK_SD),
|
||||
.d(w_DATA_CRC16_GOOD),
|
||||
.q(r_DAT_ERROR_Q),
|
||||
.en(w_DAT_ERROR_FD_EN),
|
||||
.reset((w_DAT_ERROR_FD_RST)));
|
||||
|
||||
assign w_NOT_DAT_ERROR_Q = ~r_DAT_ERROR_Q;
|
||||
|
||||
up_down_counter #(23) dat_fsm_timer
|
||||
(
|
||||
.CountIn(w_DAT_TIMER_IN),
|
||||
.CountOut(r_DAT_TIMER_OUT),
|
||||
.Load(w_DAT_TIMER_LOAD),
|
||||
.Enable(w_DAT_TIMER_EN),
|
||||
.UpDown(1'b0), // Count DOWN only
|
||||
.clk(r_G_CLK_SD),
|
||||
.reset(1'b0)); // No Reset, Just Load
|
||||
|
||||
counter #(11) dat_nibble_counter
|
||||
(
|
||||
.CountIn('0),
|
||||
.CountOut(r_DAT_COUNTER_OUT),
|
||||
.Load(1'b0),
|
||||
.Enable(w_DAT_COUNTER_EN),
|
||||
.clk(r_G_CLK_SD),
|
||||
.reset(w_DAT_COUNTER_RST));
|
||||
|
||||
regfile_p2r1w1_nibo #(.DEPTH(10), .WIDTH(4) ) regfile_cmd17_data_block // Nibble In - Nibble Out (NINO)
|
||||
(.clk(r_G_CLK_SD),
|
||||
.we1(w_NIBO_EN),
|
||||
.ra1(r_DAT_COUNTER_OUT[9:0]), // Nibble Read (to core) Address
|
||||
.rd1(r_DATA_TO_CORE), // output nibble to core
|
||||
.wa1(r_DAT_COUNTER_OUT[9:0]), // Nibble Write (to host) Address
|
||||
.wd1(r_DAT_Q)); // input nibble from card
|
||||
|
||||
crc16_sipo_np_ce crc16_sipo_np_ce_DAT3
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.RST(w_CRC16_RST),
|
||||
.i_enable(w_CRC16_EN),
|
||||
.i_message_bit(r_DAT_Q[3]),
|
||||
.o_crc16(r_DAT3_CRC16));
|
||||
|
||||
crc16_sipo_np_ce crc16_sipo_np_ce_DAT2
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.RST(w_CRC16_RST),
|
||||
.i_enable(w_CRC16_EN),
|
||||
.i_message_bit(r_DAT_Q[2]),
|
||||
.o_crc16(r_DAT2_CRC16));
|
||||
|
||||
crc16_sipo_np_ce crc16_sipo_np_ce_DAT1
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.RST(w_CRC16_RST),
|
||||
.i_enable(w_CRC16_EN),
|
||||
.i_message_bit(r_DAT_Q[1]),
|
||||
.o_crc16(r_DAT1_CRC16));
|
||||
|
||||
crc16_sipo_np_ce crc16_sipo_np_ce_DAT0
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.RST(w_CRC16_RST),
|
||||
.i_enable(w_CRC16_EN),
|
||||
.i_message_bit(r_DAT_Q[0]),
|
||||
.o_crc16(r_DAT0_CRC16));
|
||||
|
||||
|
||||
assign w_DATA_CRC16_GOOD = ({r_DAT3_CRC16, r_DAT2_CRC16, r_DAT1_CRC16, r_DAT0_CRC16}) == 64'h0000000000000000;
|
||||
|
||||
flopenr #(4) busy_bit_fd
|
||||
(.en(w_BUSY_EN),
|
||||
.clk(r_G_CLK_SD),
|
||||
.d(i_SD_DAT),
|
||||
.q(r_DAT_Q),
|
||||
.reset(w_BUSY_RST));
|
||||
|
||||
sd_clk_fsm my_clk_fsm
|
||||
(.CLK(CLK),
|
||||
.i_RST(a_RST),
|
||||
.o_DONE(w_CLOCK_CHANGE_DONE),
|
||||
.i_START(w_START_CLOCK_CHANGE),
|
||||
.o_HS_TO_INIT_CLK_DIVIDER_RST(w_HS_TO_INIT_CLK_DIVIDER_RST),
|
||||
.o_SD_CLK_SELECTED(w_SD_CLK_SELECTED),
|
||||
.i_FATAL_ERROR(w_FATAL_ERROR),
|
||||
.o_G_CLK_SD_EN(w_G_CLK_SD_EN));
|
||||
|
||||
up_down_counter #(19) cmd_fsm_timer
|
||||
(.CountIn(w_TIMER_IN),
|
||||
.CountOut(r_TIMER_OUT),
|
||||
.Load(w_TIMER_LOAD),
|
||||
.Enable(w_TIMER_EN),
|
||||
.UpDown(1'b0), // Count DOWN only
|
||||
.clk(r_G_CLK_SD),
|
||||
.reset(1'b0)); // No Reset, Just Load
|
||||
|
||||
up_down_counter #(8) cmd_fsm_counter
|
||||
(.CountIn(w_COUNTER_IN),
|
||||
.CountOut(r_COUNTER_OUT),
|
||||
.Load(w_COUNTER_LOAD),
|
||||
.Enable(w_COUNTER_EN),
|
||||
.UpDown(1'b0), // Count DOWN only
|
||||
.clk(r_G_CLK_SD),
|
||||
.reset(1'b0)); // No RESET, only LOAD
|
||||
|
||||
up_down_counter #(4) instruction_counter
|
||||
(.CountIn('0), // No CountIn, only RESET
|
||||
.CountOut(r_IC_OUT),
|
||||
.Load(1'b0), // No LOAD, only RESET
|
||||
.Enable(w_IC_EN),
|
||||
.UpDown(w_IC_UP_DOWN),
|
||||
.clk(r_G_CLK_SD),
|
||||
.reset(w_IC_RST));
|
||||
|
||||
// Clock selection
|
||||
clkdivider #(g_COUNT_WIDTH) slow_clk_divider // Divide 50 MHz to <400 KHz (Initial clock)
|
||||
(.i_COUNT_IN_MAX(i_COUNT_IN_MAX),
|
||||
.i_EN(w_SD_CLK_SELECTED),
|
||||
.i_RST(w_HS_TO_INIT_CLK_DIVIDER_RST),
|
||||
.i_CLK(CLK),
|
||||
.o_CLK(r_CLK_SD));
|
||||
|
||||
clockgater sd_clk_gater // Select which clock goes to components
|
||||
(.CLK(r_CLK_SD),
|
||||
.E(w_G_CLK_SD_EN),
|
||||
.SE(1'b0),
|
||||
.ECLK(r_G_CLK_SD));
|
||||
|
||||
clockgater to_sd_clk_gater // Enable activity on the SD_CLK line
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.E(w_SD_CLK_EN),
|
||||
.SE(1'b0),
|
||||
.ECLK(r_TO_SD_CLK));
|
||||
|
||||
flopenr #(16) RCA_register_CE
|
||||
(.clk(r_G_CLK_SD),
|
||||
.en(w_RCA_REGISTER_EN),
|
||||
.d(w_RCA_D_Q),
|
||||
.q(r_RCA_Q2),
|
||||
.reset(w_RCA_REGISTER_RST));
|
||||
|
||||
// ACMD_Detector
|
||||
flopenr #(1) index_history_fd_2to1
|
||||
(.clk(r_G_CLK_SD),
|
||||
.reset(w_CMD_TX_IS_CMD55_RST),
|
||||
.en(w_CMD_TX_IS_CMD55_EN),
|
||||
.d(r_command_index_is_55_history[2]),
|
||||
.q(r_command_index_is_55_history[1]));
|
||||
|
||||
flopenr #(1) index_history_fd_1to0
|
||||
(.clk(r_G_CLK_SD),
|
||||
.reset(w_CMD_TX_IS_CMD55_RST),
|
||||
.en(w_CMD_TX_IS_CMD55_EN),
|
||||
.d(r_command_index_is_55_history[1]),
|
||||
.q(r_command_index_is_55_history[0]));
|
||||
|
||||
|
||||
|
||||
assign r_command_index_is_55_history[2] = (w_command_index == 55);
|
||||
|
||||
|
||||
assign r_previous_command_index_was_55_q = r_command_index_is_55_history[0];
|
||||
assign r_ACMD_Q = r_previous_command_index_was_55_q; // if the previous command WAS 55, the current command is ACMD
|
||||
|
||||
assign o_SD_CLK = r_TO_SD_CLK;
|
||||
|
||||
|
||||
|
||||
// Multiplexers
|
||||
//Fetch index and argument of command
|
||||
assign w_command_content = (r_IC_OUT == 0) ? ({c_Go_Idle_State, 32'h00000000}) : // CMD0
|
||||
(r_IC_OUT == 1) ? ({c_Send_IF_State, 32'h000001FF}) : // CMD8
|
||||
(r_IC_OUT == 2) ? ({c_App_Command, 32'h00000000}) : // CMD55
|
||||
(r_IC_OUT == 3) ? ({c_SD_Send_OCR, 32'h40FF8000}) : // ACMD41
|
||||
(r_IC_OUT == 4) ? ({c_All_Send_CID, 32'h00000000}) : // CMD2
|
||||
(r_IC_OUT == 5) ? ({c_SD_Send_RCA, 32'h00000000}) : // CMD3
|
||||
(r_IC_OUT == 6) ? ({c_Select_Card, r_RCA_Q2[15:0], 16'h0000}) : // CMD7
|
||||
(r_IC_OUT == 7) ? ({c_App_Command, r_RCA_Q2[15:0], 16'h0000}) : // CMD55
|
||||
(r_IC_OUT == 8) ? ({c_Set_Bus_Width, 32'h00000002}) : // ACMD6
|
||||
(r_IC_OUT == 9) ? ({c_Switch_Function, 32'h80FFFFF1}) : // CMD6
|
||||
(r_IC_OUT == 10) ? ({c_Read_Single_Block, w_BLOCK_ADDR}) : // CMD17
|
||||
({c_Read_Single_Block, w_BLOCK_ADDR}); // when in doubt just send CMD17
|
||||
|
||||
assign w_command_index = w_command_content[45:40];
|
||||
assign w_command_arguments = w_command_content[39:8];
|
||||
assign w_command_head = {c_start_bit, c_tx_host_command, w_command_content};
|
||||
|
||||
assign w_OPCODE_Q = {r_ACMD_Q, w_command_index};
|
||||
|
||||
// TX
|
||||
|
||||
crc7_pipo tx_crc7_pipo
|
||||
(.CLK(r_G_CLK_SD),
|
||||
.i_DATA(w_command_head),
|
||||
.i_CRC_ENABLE(w_TX_CRC7_PIPO_EN),
|
||||
.RST(w_TX_CRC7_PIPO_RST),
|
||||
.o_CRC(r_TX_CRC7));
|
||||
|
||||
assign r_command_tail = {r_TX_CRC7, c_stop_bit};
|
||||
|
||||
piso_generic_ce #(40) tx_piso40_command_head
|
||||
(.clk(r_G_CLK_SD),
|
||||
.i_load(w_TX_PISO40_LOAD),
|
||||
.i_data(w_command_head),
|
||||
.i_en(w_TX_PISO40_EN),
|
||||
.o_data(w_tx_head_Q));
|
||||
|
||||
piso_generic_ce #(8) tx_piso8_command_tail
|
||||
(.clk(r_G_CLK_SD),
|
||||
.i_load(w_TX_PISO8_LOAD),
|
||||
.i_data(r_command_tail),
|
||||
.i_en(w_TX_PISO8_EN),
|
||||
.o_data(w_tx_tail_Q));
|
||||
|
||||
assign w_SD_CMD_TX_Q = (w_TX_SOURCE_SELECT == c_tx_low) ? 1'b0 :
|
||||
(w_TX_SOURCE_SELECT == c_tx_high) ? 1'b1 :
|
||||
(w_TX_SOURCE_SELECT == c_tx_head) ? w_tx_head_Q :
|
||||
(w_TX_SOURCE_SELECT == c_tx_tail) ? w_tx_tail_Q :
|
||||
1'b0;
|
||||
|
||||
assign w_SD_CMD_RX = i_SD_CMD;
|
||||
assign r_G_CLK_SD_n = ~r_G_CLK_SD;
|
||||
|
||||
flopenr #(1) sd_cmd_out_reg
|
||||
(.d(w_SD_CMD_TX_Q),
|
||||
.q(o_SD_CMD),
|
||||
.en(1'b1),
|
||||
.clk(r_G_CLK_SD_n),
|
||||
.reset(a_RST));
|
||||
|
||||
flopenr #(1) sd_cmd_out_oe_reg
|
||||
(.d(w_SD_CMD_OE),
|
||||
.q(o_SD_CMD_OE),
|
||||
.en(1'b1),
|
||||
.clk(r_G_CLK_SD_n),
|
||||
.reset(a_RST));
|
||||
|
||||
// RX
|
||||
sipo_generic_ce #(48) rx_sipo48_response_content
|
||||
(.clk(r_G_CLK_SD),
|
||||
.rst(w_RX_SIPO48_RST),
|
||||
.i_enable(w_RX_SIPO48_EN),
|
||||
.i_message_bit(w_SD_CMD_RX),
|
||||
.o_data(r_RX_RESPONSE));
|
||||
|
||||
assign r_RESPONSE_CONTENT = r_RX_RESPONSE[39:8];
|
||||
assign r_RESPONSE_INDEX = r_RX_RESPONSE[45:40];
|
||||
assign w_RCA_D_Q = r_RESPONSE_CONTENT[39:24];
|
||||
|
||||
crc7_sipo_np_ce rx_crc7_sipo
|
||||
(.clk(r_G_CLK_SD),
|
||||
.rst(w_RX_CRC7_SIPO_RST),
|
||||
.i_enable(w_RX_CRC7_SIPO_EN),
|
||||
.i_message_bit(w_SD_CMD_RX),
|
||||
.o_crc7(r_RX_CRC7_Q));
|
||||
|
||||
// Fetch control bits using r_opcode
|
||||
assign w_instruction_control_bits = (w_OPCODE_Q == ({c_CMD, c_Go_Idle_State})) ? ({c_response_type_R0_NONE, c_DAT_none, c_CMD0_mask_check_redo_bits, c_CMD0_ans_dont_redo, c_CMD0_mask_check_error_bits, c_CMD0_ans_error_free}) : // CMD0
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_All_Send_CID})) ? ({c_response_type_R2_CID_CSD, c_DAT_none, c_CMD2_mask_check_redo_bits, c_CMD2_ans_dont_redo, c_CMD2_mask_check_error_bits, c_CMD2_ans_error_free}): // CMD2
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_SD_Send_RCA})) ? ({c_response_type_R6_RCA, c_DAT_none, c_CMD3_mask_check_redo_bits, c_CMD3_ans_dont_redo, c_CMD3_mask_check_error_bits, c_CMD3_ans_error_free}) : // CMD3
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_Switch_Function})) ? ({c_response_type_R1_NORMAL, c_DAT_wide, c_CMD6_mask_check_redo_bits, c_CMD6_ans_dont_redo, c_CMD6_mask_check_error_bits, c_CMD6_ans_error_free}): // CMD6
|
||||
|
||||
(w_OPCODE_Q == ({c_ACMD, c_Set_Bus_Width})) ? ({c_response_type_R1_NORMAL, c_DAT_none, c_ACMD6_mask_check_redo_bits, c_ACMD6_ans_dont_redo, c_ACMD6_mask_check_error_bits, c_ACMD6_ans_error_free}): //ACMD6
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_Select_Card})) ? ({c_response_type_R1_NORMAL, c_DAT_busy, c_CMD7_mask_check_redo_bits, c_CMD7_ans_dont_redo, c_CMD7_mask_check_error_bits, c_CMD7_ans_error_free}): // CMD7
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_Send_IF_State})) ? ({c_response_type_R7_CIC, c_DAT_none, c_CMD8_mask_check_redo_bits, c_CMD8_ans_dont_redo, c_CMD8_mask_check_error_bits, c_CMD8_ans_error_free}): // CMD8
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_Read_Single_Block})) ? ({c_response_type_R1_NORMAL, c_DAT_block, c_CMD17_mask_check_redo_bits, c_CMD17_ans_dont_redo, c_CMD17_mask_check_error_bits, c_CMD17_ans_error_free}): // CMD17
|
||||
|
||||
(w_OPCODE_Q == ({c_ACMD, c_SD_Send_OCR})) ? ({c_response_type_R3_OCR, c_DAT_none, c_ACMD41_mask_check_redo_bits, c_ACMD41_ans_dont_redo, c_ACMD41_mask_check_error_bits, c_ACMD41_ans_error_free}) : //ACMD41
|
||||
|
||||
(w_OPCODE_Q == ({c_CMD, c_App_Command})) ? ({c_response_type_R1_NORMAL, c_DAT_none, c_CMD55_mask_check_redo_bits, c_CMD55_ans_dont_redo, c_CMD55_mask_check_error_bits, c_CMD55_ans_error_free}) : // CMD55
|
||||
|
||||
(w_OPCODE_Q == ({c_ACMD, c_App_Command})) ? ({c_response_type_R1_NORMAL, c_DAT_none, c_ACMD55_mask_check_redo_bits, c_ACMD55_ans_dont_redo, c_ACMD55_mask_check_error_bits, c_ACMD55_ans_error_free}) : //ACMD55
|
||||
|
||||
({c_response_type_R1_NORMAL, c_DAT_none, c_ACMD55_mask_check_redo_bits, c_ACMD55_ans_dont_redo, c_ACMD55_mask_check_error_bits, c_ACMD55_ans_error_free}); // when in doubt just send ACMD55
|
||||
|
||||
assign w_R_TYPE = w_instruction_control_bits[132:130];
|
||||
assign w_USES_DAT = w_instruction_control_bits[129:128];
|
||||
assign w_NO_REDO_MASK = w_instruction_control_bits[127:96];
|
||||
assign w_NO_REDO_ANS = w_instruction_control_bits[95:64];
|
||||
assign w_NO_ERROR_MASK = w_instruction_control_bits[63:32];
|
||||
assign w_NO_ERROR_ANS = w_instruction_control_bits[31:0];
|
||||
|
||||
|
||||
endmodule
|
||||
|
55
wally-pipelined/src/sdc/simple_timer.sv
Normal file
55
wally-pipelined/src/sdc/simple_timer.sv
Normal file
@ -0,0 +1,55 @@
|
||||
///////////////////////////////////////////
|
||||
// simple_timer.sv
|
||||
//
|
||||
// Written: Ross Thompson September 20, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: SD card controller
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module simple_timer #(parameter BUS_WIDTH = 4)
|
||||
(
|
||||
input logic [BUS_WIDTH-1:0] VALUE,
|
||||
input logic START,
|
||||
output logic FLAG,
|
||||
input logic RST,
|
||||
input logic CLK);
|
||||
|
||||
|
||||
logic [0:2**BUS_WIDTH-1] count;
|
||||
logic timer_en;
|
||||
|
||||
assign timer_en = count != 0;
|
||||
|
||||
always_ff @(posedge CLK, posedge RST) begin
|
||||
if (RST) begin
|
||||
count <= '0;
|
||||
end else if (START) begin
|
||||
count <= VALUE - 1'b1;
|
||||
end else if(timer_en) begin
|
||||
count <= count - 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
assign FLAG = count != 0;
|
||||
|
||||
endmodule
|
||||
|
53
wally-pipelined/src/sdc/sipo_generic_ce.sv
Normal file
53
wally-pipelined/src/sdc/sipo_generic_ce.sv
Normal file
@ -0,0 +1,53 @@
|
||||
///////////////////////////////////////////
|
||||
// sipo_generic_ce
|
||||
//
|
||||
// Written: Ross Thompson September 20, 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: serial to n-bit parallel shift register using register_ce.
|
||||
// When given a n-bit word as input transmit the message serially MSB (leftmost)
|
||||
// bit first.
|
||||
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module sipo_generic_ce #(g_BUS_WIDTH)
|
||||
(input logic clk,
|
||||
input logic rst,
|
||||
input logic i_enable, // data valid, write to register
|
||||
input logic i_message_bit, // serial data
|
||||
output logic [g_BUS_WIDTH-1:0] o_data // message received, parallel data
|
||||
);
|
||||
|
||||
logic [g_BUS_WIDTH-1:0] w_reg_d;
|
||||
logic [g_BUS_WIDTH-1:0] r_reg_q;
|
||||
|
||||
flopenr #(g_BUS_WIDTH) shiftReg
|
||||
(.d(w_reg_d),
|
||||
.q(r_reg_q),
|
||||
.en(i_enable),
|
||||
.reset(rst),
|
||||
.clk(clk));
|
||||
|
||||
assign w_reg_d = {r_reg_q[g_BUS_WIDTH-2:0], i_message_bit};
|
||||
|
||||
assign o_data = r_reg_q;
|
||||
|
||||
endmodule
|
384
wally-pipelined/src/sdc/tb/ramdisk2.hex
Normal file
384
wally-pipelined/src/sdc/tb/ramdisk2.hex
Normal file
@ -0,0 +1,384 @@
|
||||
@20000000 10 32 54 76
|
||||
@20000004 00 01 02 03
|
||||
@20000008 04 05 06 07
|
||||
@2000000C 08 09 0A 0B
|
||||
@20000010 0C 0D 0E 0F
|
||||
@20000014 0F 0E 0D 0C
|
||||
@20000018 0B 0A 09 08
|
||||
@2000001C 07 06 05 04
|
||||
@20000020 03 02 01 00
|
||||
@20000024 10 32 54 76
|
||||
@20000028 10 32 54 76
|
||||
@2000002C 10 32 54 76
|
||||
@20000030 10 32 54 76
|
||||
@20000034 10 32 54 76
|
||||
@20000038 10 32 54 76
|
||||
@2000003C 10 32 54 76
|
||||
@20000040 10 32 54 76
|
||||
@20000044 10 32 54 76
|
||||
@20000048 10 32 54 76
|
||||
@2000004C 10 32 54 76
|
||||
@20000050 10 32 54 76
|
||||
@20000054 10 32 54 76
|
||||
@20000058 10 32 54 76
|
||||
@2000005C 10 32 54 76
|
||||
@20000060 10 32 54 76
|
||||
@20000064 10 32 54 76
|
||||
@20000068 10 32 54 76
|
||||
@2000006C 10 32 54 76
|
||||
@20000070 10 32 54 76
|
||||
@20000074 10 32 54 76
|
||||
@20000078 10 32 54 76
|
||||
@2000007C 10 32 54 76
|
||||
@20000080 10 32 54 76
|
||||
@20000084 10 32 54 76
|
||||
@20000088 10 32 54 76
|
||||
@2000008C 10 32 54 76
|
||||
@20000090 10 32 54 76
|
||||
@20000094 10 32 54 76
|
||||
@20000098 10 32 54 76
|
||||
@2000009C 10 32 54 76
|
||||
@200000A0 10 32 54 76
|
||||
@200000A4 10 32 54 76
|
||||
@200000A8 10 32 54 76
|
||||
@200000AC 10 32 54 76
|
||||
@200000B0 10 32 54 76
|
||||
@200000B4 10 32 54 76
|
||||
@200000B8 10 32 54 76
|
||||
@200000BC 10 32 54 76
|
||||
@200000C0 10 32 54 76
|
||||
@200000C4 10 32 54 76
|
||||
@200000C8 10 32 54 76
|
||||
@200000CC 10 32 54 76
|
||||
@200000D0 10 32 54 76
|
||||
@200000D4 10 32 54 76
|
||||
@200000D8 10 32 54 76
|
||||
@200000DC 10 32 54 76
|
||||
@200000E0 10 32 54 76
|
||||
@200000E4 10 32 54 76
|
||||
@200000E8 10 32 54 76
|
||||
@200000EC 10 32 54 76
|
||||
@200000F0 10 32 54 76
|
||||
@200000F4 10 32 54 76
|
||||
@200000F8 10 32 54 76
|
||||
@200000FC 10 32 54 76
|
||||
@20000100 10 32 54 76
|
||||
@20000104 10 32 54 76
|
||||
@20000108 10 32 54 76
|
||||
@2000010C 10 32 54 76
|
||||
@20000110 10 32 54 76
|
||||
@20000114 10 32 54 76
|
||||
@20000118 10 32 54 76
|
||||
@2000011C 10 32 54 76
|
||||
@20000120 10 32 54 76
|
||||
@20000124 10 32 54 76
|
||||
@20000128 10 32 54 76
|
||||
@2000012C 10 32 54 76
|
||||
@20000130 10 32 54 76
|
||||
@20000134 10 32 54 76
|
||||
@20000138 10 32 54 76
|
||||
@2000013C 10 32 54 76
|
||||
@20000140 10 32 54 76
|
||||
@20000144 10 32 54 76
|
||||
@20000148 10 32 54 76
|
||||
@2000014C 10 32 54 76
|
||||
@20000150 10 32 54 76
|
||||
@20000154 10 32 54 76
|
||||
@20000158 10 32 54 76
|
||||
@2000015C 10 32 54 76
|
||||
@20000160 10 32 54 76
|
||||
@20000164 10 32 54 76
|
||||
@20000168 10 32 54 76
|
||||
@2000016C 10 32 54 76
|
||||
@20000170 10 32 54 76
|
||||
@20000174 10 32 54 76
|
||||
@20000178 10 32 54 76
|
||||
@2000017C 10 32 54 76
|
||||
@20000180 10 32 54 76
|
||||
@20000184 10 32 54 76
|
||||
@20000188 10 32 54 76
|
||||
@2000018C 10 32 54 76
|
||||
@20000190 10 32 54 76
|
||||
@20000194 10 32 54 76
|
||||
@20000198 10 32 54 76
|
||||
@2000019C 10 32 54 76
|
||||
@200001A0 10 32 54 76
|
||||
@200001A4 10 32 54 76
|
||||
@200001A8 10 32 54 76
|
||||
@200001AC 10 32 54 76
|
||||
@200001B0 10 32 54 76
|
||||
@200001B4 10 32 54 76
|
||||
@200001B8 10 32 54 76
|
||||
@200001BC 10 32 54 76
|
||||
@200001C0 10 32 54 76
|
||||
@200001C4 10 32 54 76
|
||||
@200001C8 10 32 54 76
|
||||
@200001CC 10 32 54 76
|
||||
@200001D0 10 32 54 76
|
||||
@200001D4 10 32 54 76
|
||||
@200001D8 10 32 54 76
|
||||
@200001DC 10 32 54 76
|
||||
@200001E0 10 32 54 76
|
||||
@200001E4 10 32 54 76
|
||||
@200001E8 10 32 54 76
|
||||
@200001EC 10 32 54 76
|
||||
@200001F0 10 32 54 76
|
||||
@200001F4 10 32 54 76
|
||||
@200001F8 10 32 54 76
|
||||
@200001FC 10 32 54 76
|
||||
@1ffff0000 00 00 00 00
|
||||
@1ffff0004 00 00 00 00
|
||||
@1ffff0008 00 00 00 00
|
||||
@1ffff000c 00 00 00 00
|
||||
@1ffff0010 00 00 00 00
|
||||
@1ffff0014 00 00 00 00
|
||||
@1ffff0018 00 00 00 00
|
||||
@1ffff001c 00 00 00 00
|
||||
@1ffff0020 00 00 00 00
|
||||
@1ffff0024 00 00 00 00
|
||||
@1ffff0028 00 00 00 00
|
||||
@1ffff002c 00 00 00 00
|
||||
@1ffff0030 00 00 00 00
|
||||
@1ffff0034 00 00 00 00
|
||||
@1ffff0038 00 00 00 00
|
||||
@1ffff003c 00 00 00 00
|
||||
@1ffff0040 00 00 00 00
|
||||
@1ffff0044 00 00 00 00
|
||||
@1ffff0048 00 00 00 00
|
||||
@1ffff004c 00 00 00 00
|
||||
@1ffff0050 00 00 00 00
|
||||
@1ffff0054 00 00 00 00
|
||||
@1ffff0058 00 00 00 00
|
||||
@1ffff005c 00 00 00 00
|
||||
@1ffff0060 00 00 00 00
|
||||
@1ffff0064 00 00 00 00
|
||||
@1ffff0068 00 00 00 00
|
||||
@1ffff006C 00 00 00 00
|
||||
@1ffff0070 00 00 00 00
|
||||
@1ffff0074 00 00 00 00
|
||||
@1ffff0078 00 00 00 00
|
||||
@1ffff007c 00 00 00 00
|
||||
@1ffff0080 00 00 00 00
|
||||
@1ffff0084 00 00 00 00
|
||||
@1ffff0088 00 00 00 00
|
||||
@1ffff008c 00 00 00 00
|
||||
@1ffff0090 00 00 00 00
|
||||
@1ffff0094 00 00 00 00
|
||||
@1ffff0098 00 00 00 00
|
||||
@1ffff009c 00 00 00 00
|
||||
@1ffff00a0 00 00 00 00
|
||||
@1ffff00a4 00 00 00 00
|
||||
@1ffff00a8 00 00 00 00
|
||||
@1ffff00ac 00 00 00 00
|
||||
@1ffff00b0 00 00 00 00
|
||||
@1ffff00b4 00 00 00 00
|
||||
@1ffff00b8 00 00 00 00
|
||||
@1ffff00bc 00 00 00 00
|
||||
@1ffff00c0 00 00 00 00
|
||||
@1ffff00c4 00 00 00 00
|
||||
@1ffff00c8 00 00 00 00
|
||||
@1ffff00cc 00 00 00 00
|
||||
@1ffff00d0 00 00 00 00
|
||||
@1ffff00d4 00 00 00 00
|
||||
@1ffff00d8 00 00 00 00
|
||||
@1ffff00dc 00 00 00 00
|
||||
@1ffff00e0 00 00 00 00
|
||||
@1ffff00e4 00 00 00 00
|
||||
@1ffff00e8 00 00 00 00
|
||||
@1ffff00ec 00 00 00 00
|
||||
@1ffff00f0 00 00 00 00
|
||||
@1ffff00f4 00 00 00 00
|
||||
@1ffff00f8 00 00 00 00
|
||||
@1ffff00fc 00 00 00 00
|
||||
@1ffff0100 00 00 00 00
|
||||
@1ffff0104 00 00 00 00
|
||||
@1ffff0108 00 00 00 00
|
||||
@1ffff010c 00 00 00 00
|
||||
@1ffff0110 00 00 00 00
|
||||
@1ffff0114 00 00 00 00
|
||||
@1ffff0118 00 00 00 00
|
||||
@1ffff011c 00 00 00 00
|
||||
@1ffff0120 00 00 00 00
|
||||
@1ffff0124 00 00 00 00
|
||||
@1ffff0128 00 00 00 00
|
||||
@1ffff012c 00 00 00 00
|
||||
@1ffff0130 00 00 00 00
|
||||
@1ffff0134 00 00 00 00
|
||||
@1ffff0138 00 00 00 00
|
||||
@1ffff013c 00 00 00 00
|
||||
@1ffff0140 00 00 00 00
|
||||
@1ffff0144 00 00 00 00
|
||||
@1ffff0148 00 00 00 00
|
||||
@1ffff014c 00 00 00 00
|
||||
@1ffff0150 00 00 00 00
|
||||
@1ffff0154 00 00 00 00
|
||||
@1ffff0158 00 00 00 00
|
||||
@1ffff015c 00 00 00 00
|
||||
@1ffff0160 00 00 00 00
|
||||
@1ffff0164 00 00 00 00
|
||||
@1ffff0168 00 00 00 00
|
||||
@1ffff016C 00 00 00 00
|
||||
@1ffff0170 00 00 00 00
|
||||
@1ffff0174 00 00 00 00
|
||||
@1ffff0178 00 00 00 00
|
||||
@1ffff017c 00 00 00 00
|
||||
@1ffff0180 00 00 00 00
|
||||
@1ffff0184 00 00 00 00
|
||||
@1ffff0188 00 00 00 00
|
||||
@1ffff018c 00 00 00 00
|
||||
@1ffff0190 00 00 00 00
|
||||
@1ffff0194 00 00 00 00
|
||||
@1ffff0198 00 00 00 00
|
||||
@1ffff019c 00 00 00 00
|
||||
@1ffff01a0 00 00 00 00
|
||||
@1ffff01a4 00 00 00 00
|
||||
@1ffff01a8 00 00 00 00
|
||||
@1ffff01ac 00 00 00 00
|
||||
@1ffff01b0 00 00 00 00
|
||||
@1ffff01b4 00 00 00 00
|
||||
@1ffff01b8 00 00 00 00
|
||||
@1ffff01bc 00 00 00 00
|
||||
@1ffff01c0 00 00 00 00
|
||||
@1ffff01c4 00 00 00 00
|
||||
@1ffff01c8 00 00 00 00
|
||||
@1ffff01cc 00 00 00 00
|
||||
@1ffff01d0 00 00 00 00
|
||||
@1ffff01d4 00 00 00 00
|
||||
@1ffff01d8 00 00 00 00
|
||||
@1ffff01dc 00 00 00 00
|
||||
@1ffff01e0 00 00 00 00
|
||||
@1ffff01e4 00 00 00 00
|
||||
@1ffff01e8 00 00 00 00
|
||||
@1ffff01ec 00 00 00 00
|
||||
@1ffff01f0 00 00 00 00
|
||||
@1ffff01f4 00 00 00 00
|
||||
@1ffff01f8 00 00 00 00
|
||||
@1ffff01fc 00 00 00 00
|
||||
@0ffff0000 00 00 00 00
|
||||
@0ffff0004 00 00 00 00
|
||||
@0ffff0008 00 00 00 00
|
||||
@0ffff000c 00 00 00 00
|
||||
@0ffff0010 00 00 00 00
|
||||
@0ffff0014 00 00 00 00
|
||||
@0ffff0018 00 00 00 00
|
||||
@0ffff001c 00 00 00 00
|
||||
@0ffff0020 00 00 00 00
|
||||
@0ffff0024 00 00 00 00
|
||||
@0ffff0028 00 00 00 00
|
||||
@0ffff002c 00 00 00 00
|
||||
@0ffff0030 00 00 00 00
|
||||
@0ffff0034 00 00 00 00
|
||||
@0ffff0038 00 00 00 00
|
||||
@0ffff003c 00 00 00 00
|
||||
@0ffff0040 00 00 00 00
|
||||
@0ffff0044 00 00 00 00
|
||||
@0ffff0048 00 00 00 00
|
||||
@0ffff004c 00 00 00 00
|
||||
@0ffff0050 00 00 00 00
|
||||
@0ffff0054 00 00 00 00
|
||||
@0ffff0058 00 00 00 00
|
||||
@0ffff005c 00 00 00 00
|
||||
@0ffff0060 00 00 00 00
|
||||
@0ffff0064 00 00 00 00
|
||||
@0ffff0068 00 00 00 00
|
||||
@0ffff006C 00 00 00 00
|
||||
@0ffff0070 00 00 00 00
|
||||
@0ffff0074 00 00 00 00
|
||||
@0ffff0078 00 00 00 00
|
||||
@0ffff007c 00 00 00 00
|
||||
@0ffff0080 00 00 00 00
|
||||
@0ffff0084 00 00 00 00
|
||||
@0ffff0088 00 00 00 00
|
||||
@0ffff008c 00 00 00 00
|
||||
@0ffff0090 00 00 00 00
|
||||
@0ffff0094 00 00 00 00
|
||||
@0ffff0098 00 00 00 00
|
||||
@0ffff009c 00 00 00 00
|
||||
@0ffff00a0 00 00 00 00
|
||||
@0ffff00a4 00 00 00 00
|
||||
@0ffff00a8 00 00 00 00
|
||||
@0ffff00ac 00 00 00 00
|
||||
@0ffff00b0 00 00 00 00
|
||||
@0ffff00b4 00 00 00 00
|
||||
@0ffff00b8 00 00 00 00
|
||||
@0ffff00bc 00 00 00 00
|
||||
@0ffff00c0 00 00 00 00
|
||||
@0ffff00c4 00 00 00 00
|
||||
@0ffff00c8 00 00 00 00
|
||||
@0ffff00cc 00 00 00 00
|
||||
@0ffff00d0 00 00 00 00
|
||||
@0ffff00d4 00 00 00 00
|
||||
@0ffff00d8 00 00 00 00
|
||||
@0ffff00dc 00 00 00 00
|
||||
@0ffff00e0 00 00 00 00
|
||||
@0ffff00e4 00 00 00 00
|
||||
@0ffff00e8 00 00 00 00
|
||||
@0ffff00ec 00 00 00 00
|
||||
@0ffff00f0 00 00 00 00
|
||||
@0ffff00f4 00 00 00 00
|
||||
@0ffff00f8 00 00 00 00
|
||||
@0ffff00fc 00 00 00 00
|
||||
@0ffff0100 00 00 00 00
|
||||
@0ffff0104 00 00 00 00
|
||||
@0ffff0108 00 00 00 00
|
||||
@0ffff010c 00 00 00 00
|
||||
@0ffff0110 00 00 00 00
|
||||
@0ffff0114 00 00 00 00
|
||||
@0ffff0118 00 00 00 00
|
||||
@0ffff011c 00 00 00 00
|
||||
@0ffff0120 00 00 00 00
|
||||
@0ffff0124 00 00 00 00
|
||||
@0ffff0128 00 00 00 00
|
||||
@0ffff012c 00 00 00 00
|
||||
@0ffff0130 00 00 00 00
|
||||
@0ffff0134 00 00 00 00
|
||||
@0ffff0138 00 00 00 00
|
||||
@0ffff013c 00 00 00 00
|
||||
@0ffff0140 00 00 00 00
|
||||
@0ffff0144 00 00 00 00
|
||||
@0ffff0148 00 00 00 00
|
||||
@0ffff014c 00 00 00 00
|
||||
@0ffff0150 00 00 00 00
|
||||
@0ffff0154 00 00 00 00
|
||||
@0ffff0158 00 00 00 00
|
||||
@0ffff015c 00 00 00 00
|
||||
@0ffff0160 00 00 00 00
|
||||
@0ffff0164 00 00 00 00
|
||||
@0ffff0168 00 00 00 00
|
||||
@0ffff016C 00 00 00 00
|
||||
@0ffff0170 00 00 00 00
|
||||
@0ffff0174 00 00 00 00
|
||||
@0ffff0178 00 00 00 00
|
||||
@0ffff017c 00 00 00 00
|
||||
@0ffff0180 00 00 00 00
|
||||
@0ffff0184 00 00 00 00
|
||||
@0ffff0188 00 00 00 00
|
||||
@0ffff018c 00 00 00 00
|
||||
@0ffff0190 00 00 00 00
|
||||
@0ffff0194 00 00 00 00
|
||||
@0ffff0198 00 00 00 00
|
||||
@0ffff019c 00 00 00 00
|
||||
@0ffff01a0 00 00 00 00
|
||||
@0ffff01a4 00 00 00 00
|
||||
@0ffff01a8 00 00 00 00
|
||||
@0ffff01ac 00 00 00 00
|
||||
@0ffff01b0 00 00 00 00
|
||||
@0ffff01b4 00 00 00 00
|
||||
@0ffff01b8 00 00 00 00
|
||||
@0ffff01bc 00 00 00 00
|
||||
@0ffff01c0 00 00 00 00
|
||||
@0ffff01c4 00 00 00 00
|
||||
@0ffff01c8 00 00 00 00
|
||||
@0ffff01cc 00 00 00 00
|
||||
@0ffff01d0 00 00 00 00
|
||||
@0ffff01d4 00 00 00 00
|
||||
@0ffff01d8 00 00 00 00
|
||||
@0ffff01dc 00 00 00 00
|
||||
@0ffff01e0 00 00 00 00
|
||||
@0ffff01e4 00 00 00 00
|
||||
@0ffff01e8 00 00 00 00
|
||||
@0ffff01ec 00 00 00 00
|
||||
@0ffff01f0 00 00 00 00
|
||||
@0ffff01f4 00 00 00 00
|
||||
@0ffff01f8 00 00 00 00
|
||||
@0ffff01fc 00 00 00 00
|
17
wally-pipelined/src/sdc/tb/run_tb.do
Normal file
17
wally-pipelined/src/sdc/tb/run_tb.do
Normal file
@ -0,0 +1,17 @@
|
||||
onbreak {resume}
|
||||
|
||||
# create library
|
||||
if [file exists work] {
|
||||
vdel -all
|
||||
}
|
||||
vlib work
|
||||
|
||||
vlog +incdir+../../../config/rv64ic +incdir+../../../config/shared ../../../testbench/common/*.sv ../../*/*.sv sd_top_tb.sv sdModel.sv sd_crc_7.sv sd_crc_16.sv -suppress 2583
|
||||
|
||||
vopt -fsmdebug +acc -gDEBUG=1 work.sd_top_tb -o workopt
|
||||
vsim workopt -fsmdebug
|
||||
|
||||
do wave.do
|
||||
add log -r /*
|
||||
|
||||
run 3000 us
|
1052
wally-pipelined/src/sdc/tb/sdModel.sv
Normal file
1052
wally-pipelined/src/sdc/tb/sdModel.sv
Normal file
File diff suppressed because it is too large
Load Diff
48
wally-pipelined/src/sdc/tb/sd_crc_16.sv
Normal file
48
wally-pipelined/src/sdc/tb/sd_crc_16.sv
Normal file
@ -0,0 +1,48 @@
|
||||
// ==========================================================================
|
||||
// CRC Generation Unit - Linear Feedback Shift Register implementation
|
||||
// (c) Kay Gorontzi, GHSi.de, distributed under the terms of LGPL
|
||||
// https://www.ghsi.de/CRC/index.php?
|
||||
|
||||
// https://www.ghsi.de/CRC/index.php?
|
||||
// =========================================================================
|
||||
module sd_crc_16(BITVAL, Enable, CLK, RST, CRC);
|
||||
input BITVAL;// Next input bit
|
||||
input Enable;
|
||||
input CLK; // Current bit valid (Clock)
|
||||
input RST; // Init CRC value
|
||||
output reg [15:0] CRC; // Current output CRC value
|
||||
|
||||
|
||||
// We need output registers
|
||||
wire inv;
|
||||
|
||||
assign inv = BITVAL ^ CRC[15]; // XOR required?
|
||||
|
||||
always @(posedge CLK or posedge RST) begin
|
||||
if (RST) begin
|
||||
CRC = 0;
|
||||
|
||||
end
|
||||
else begin
|
||||
if (Enable==1) begin
|
||||
CRC[15] = CRC[14];
|
||||
CRC[14] = CRC[13];
|
||||
CRC[13] = CRC[12];
|
||||
CRC[12] = CRC[11] ^ inv;
|
||||
CRC[11] = CRC[10];
|
||||
CRC[10] = CRC[9];
|
||||
CRC[9] = CRC[8];
|
||||
CRC[8] = CRC[7];
|
||||
CRC[7] = CRC[6];
|
||||
CRC[6] = CRC[5];
|
||||
CRC[5] = CRC[4] ^ inv;
|
||||
CRC[4] = CRC[3];
|
||||
CRC[3] = CRC[2];
|
||||
CRC[2] = CRC[1];
|
||||
CRC[1] = CRC[0];
|
||||
CRC[0] = inv;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
34
wally-pipelined/src/sdc/tb/sd_crc_7.sv
Normal file
34
wally-pipelined/src/sdc/tb/sd_crc_7.sv
Normal file
@ -0,0 +1,34 @@
|
||||
module sd_crc_7(BITVAL, Enable, CLK, RST, CRC);
|
||||
input BITVAL;// Next input bit
|
||||
input Enable;
|
||||
input CLK; // Current bit valid (Clock)
|
||||
input RST; // Init CRC value
|
||||
output [6:0] CRC; // Current output CRC value
|
||||
|
||||
reg [6:0] CRC;
|
||||
// We need output registers
|
||||
wire inv;
|
||||
|
||||
assign inv = BITVAL ^ CRC[6]; // XOR required?
|
||||
|
||||
|
||||
always @(posedge CLK or posedge RST) begin
|
||||
if (RST) begin
|
||||
CRC = 0;
|
||||
|
||||
end
|
||||
else begin
|
||||
if (Enable==1) begin
|
||||
CRC[6] = CRC[5];
|
||||
CRC[5] = CRC[4];
|
||||
CRC[4] = CRC[3];
|
||||
CRC[3] = CRC[2] ^ inv;
|
||||
CRC[2] = CRC[1];
|
||||
CRC[1] = CRC[0];
|
||||
CRC[0] = inv;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
89
wally-pipelined/src/sdc/tb/sd_defines.h
Normal file
89
wally-pipelined/src/sdc/tb/sd_defines.h
Normal file
@ -0,0 +1,89 @@
|
||||
//Read the documentation before changing values
|
||||
|
||||
`define BIG_ENDIAN
|
||||
//`define LITLE_ENDIAN
|
||||
|
||||
`define SIM
|
||||
//`define SYN
|
||||
|
||||
`define SDC_IRQ_ENABLE
|
||||
|
||||
`define ACTEL
|
||||
|
||||
//`define CUSTOM
|
||||
//`define ALTERA
|
||||
//`define XLINX
|
||||
//`define SIMULATOR
|
||||
|
||||
`define RESEND_MAX_CNT 3
|
||||
|
||||
//MAX 255 BD
|
||||
//BD size/4
|
||||
|
||||
`ifdef ACTEL
|
||||
`define BD_WIDTH 5
|
||||
`define BD_SIZE 32
|
||||
`define RAM_MEM_WIDTH_16
|
||||
`define RAM_MEM_WIDTH 16
|
||||
|
||||
`endif
|
||||
|
||||
//`ifdef CUSTOM
|
||||
// `define NR_O_BD_4
|
||||
// `define BD_WIDTH 5
|
||||
// `define BD_SIZE 32
|
||||
// `define RAM_MEM_WIDTH_32
|
||||
// `define RAM_MEM_WIDTH 32
|
||||
//`endif
|
||||
|
||||
|
||||
|
||||
`ifdef SYN
|
||||
`define RESET_CLK_DIV 0
|
||||
`define MEM_OFFSET 4
|
||||
`endif
|
||||
|
||||
`ifdef SIM
|
||||
`define RESET_CLK_DIV 0
|
||||
`define MEM_OFFSET 4
|
||||
`endif
|
||||
|
||||
//SD-Clock Defines ---------
|
||||
//Use bus clock or a seperate clock
|
||||
`define SDC_CLK_BUS_CLK
|
||||
//`define SDC_CLK_SEP
|
||||
|
||||
// Use of internal clock divider
|
||||
//`define SDC_CLK_STATIC
|
||||
`define SDC_CLK_DYNAMIC
|
||||
|
||||
|
||||
//SD DATA-transfer defines---
|
||||
`define BLOCK_SIZE 512
|
||||
`define SD_BUS_WIDTH_4
|
||||
`define SD_BUS_W 4
|
||||
|
||||
//at 512 bytes per block, equal 1024 4 bytes writings with a bus width of 4, add 2 for startbit and Z bit.
|
||||
//Add 18 for crc, endbit and z.
|
||||
`define BIT_BLOCK 1044
|
||||
`define CRC_OFF 19
|
||||
`define BIT_BLOCK_REC 1024
|
||||
`define BIT_CRC_CYCLE 16
|
||||
|
||||
|
||||
//FIFO defines---------------
|
||||
`define FIFO_RX_MEM_DEPTH 8
|
||||
`define FIFO_RX_MEM_ADR_SIZE 4
|
||||
|
||||
`define FIFO_TX_MEM_DEPTH 8
|
||||
`define FIFO_TX_MEM_ADR_SIZE 4
|
||||
//---------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
115
wally-pipelined/src/sdc/tb/sd_top_tb.sv
Normal file
115
wally-pipelined/src/sdc/tb/sd_top_tb.sv
Normal file
@ -0,0 +1,115 @@
|
||||
///////////////////////////////////////////
|
||||
// sd_top_tb.sv
|
||||
//
|
||||
// Written: Ross Thompson September 20, 2021
|
||||
// Modified:
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
|
||||
module sd_top_tb();
|
||||
|
||||
|
||||
localparam integer g_COUNT_WIDTH = 8;
|
||||
|
||||
logic a_RST;
|
||||
logic i_SD_CMD;
|
||||
logic o_SD_CMD;
|
||||
logic o_SD_CMD_OE;
|
||||
wire [3:0] i_SD_DAT;
|
||||
logic o_SD_CLK;
|
||||
logic [32:9] i_BLOCK_ADDR;
|
||||
logic [g_COUNT_WIDTH-1:0] i_COUNT_IN_MAX;
|
||||
|
||||
logic o_READY_FOR_READ;
|
||||
logic i_READ_REQUEST;
|
||||
logic [3:0] o_DATA_TO_CORE;
|
||||
logic o_DATA_VALID;
|
||||
logic o_LAST_NIBBLE;
|
||||
|
||||
// Driver
|
||||
wire PAD;
|
||||
|
||||
logic r_CLK;
|
||||
|
||||
|
||||
// clock
|
||||
|
||||
sd_top #(g_COUNT_WIDTH) DUT
|
||||
(.CLK(r_CLK),
|
||||
.a_RST(a_RST),
|
||||
.i_SD_CMD(i_SD_CMD),
|
||||
.o_SD_CMD(o_SD_CMD),
|
||||
.o_SD_CMD_OE(o_SD_CMD_OE),
|
||||
.i_SD_DAT(i_SD_DAT),
|
||||
.o_SD_CLK(o_SD_CLK),
|
||||
.i_BLOCK_ADDR(i_BLOCK_ADDR),
|
||||
.o_READY_FOR_READ(o_READY_FOR_READ),
|
||||
.i_READ_REQUEST(i_READ_REQUEST),
|
||||
.o_DATA_TO_CORE(o_DATA_TO_CORE),
|
||||
.o_DATA_VALID(o_DATA_VALID),
|
||||
.o_LAST_NIBBLE(o_LAST_NIBBLE),
|
||||
.i_COUNT_IN_MAX(i_COUNT_IN_MAX),
|
||||
.LIMIT_SD_TIMERS(1'b1));
|
||||
|
||||
sdModel sdcard
|
||||
(.sdClk(o_SD_CLK),
|
||||
.cmd(PAD),
|
||||
.dat(i_SD_DAT));
|
||||
|
||||
// tri state pad
|
||||
// replace with I/O standard cell or FPGA gate.
|
||||
assign PAD = o_SD_CMD_OE ? o_SD_CMD : 1'bz;
|
||||
assign i_SD_CMD = PAD;
|
||||
|
||||
|
||||
always
|
||||
begin
|
||||
r_CLK = 1; # 5; r_CLK = 0; # 5;
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
|
||||
a_RST = 1'b0;
|
||||
i_BLOCK_ADDR = 24'h100000;
|
||||
i_COUNT_IN_MAX = '0;
|
||||
i_READ_REQUEST = 1'b0;
|
||||
|
||||
# 5;
|
||||
i_COUNT_IN_MAX = -62;
|
||||
|
||||
# 10;
|
||||
a_RST = 1'b1;
|
||||
|
||||
# 4800;
|
||||
|
||||
a_RST = 1'b0;
|
||||
|
||||
# 2000000;
|
||||
i_READ_REQUEST = 1'b0;
|
||||
# 10000;
|
||||
i_READ_REQUEST = 1'b1;
|
||||
# 10000;
|
||||
i_READ_REQUEST = 1'b0;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
127
wally-pipelined/src/sdc/tb/wave.do
Normal file
127
wally-pipelined/src/sdc/tb/wave.do
Normal file
@ -0,0 +1,127 @@
|
||||
onerror {resume}
|
||||
quietly WaveActivateNextPane {} 0
|
||||
add wave -noupdate /sd_top_tb/DUT/a_RST
|
||||
add wave -noupdate /sd_top_tb/DUT/CLK
|
||||
add wave -noupdate /sd_top_tb/DUT/i_BLOCK_ADDR
|
||||
add wave -noupdate /sd_top_tb/DUT/i_READ_REQUEST
|
||||
add wave -noupdate /sd_top_tb/DUT/i_COUNT_IN_MAX
|
||||
add wave -noupdate /sd_top_tb/DUT/LIMIT_SD_TIMERS
|
||||
add wave -noupdate /sd_top_tb/DUT/o_READY_FOR_READ
|
||||
add wave -noupdate /sd_top_tb/DUT/o_SD_RESTARTING
|
||||
add wave -noupdate /sd_top_tb/DUT/o_DATA_TO_CORE
|
||||
add wave -noupdate /sd_top_tb/DUT/o_DATA_VALID
|
||||
add wave -noupdate /sd_top_tb/DUT/o_LAST_NIBBLE
|
||||
add wave -noupdate /sd_top_tb/DUT/o_ERROR_CODE_Q
|
||||
add wave -noupdate /sd_top_tb/DUT/o_FATAL_ERROR
|
||||
add wave -noupdate -expand -group interface /sd_top_tb/DUT/o_SD_CLK
|
||||
add wave -noupdate -expand -group interface /sd_top_tb/DUT/o_SD_CMD
|
||||
add wave -noupdate -expand -group interface /sd_top_tb/DUT/o_SD_CMD_OE
|
||||
add wave -noupdate -expand -group interface /sd_top_tb/DUT/i_SD_CMD
|
||||
add wave -noupdate -expand -group interface /sd_top_tb/DUT/i_SD_DAT
|
||||
add wave -noupdate -label {cmd fsm} /sd_top_tb/DUT/my_sd_cmd_fsm/r_curr_state
|
||||
add wave -noupdate -label {dat fsm} /sd_top_tb/DUT/my_sd_dat_fsm/r_curr_state
|
||||
add wave -noupdate -label {clk fsm} /sd_top_tb/DUT/my_clk_fsm/r_curr_state
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_RST
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_TIMER_OUT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_COUNTER_OUT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_CLOCK_CHANGE_DONE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_IC_OUT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_USES_DAT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_OPCODE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_R_TYPE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_NO_REDO_MASK
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_NO_REDO_ANS
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_NO_ERROR_MASK
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_NO_ERROR_ANS
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_SD_CMD_RX
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_RESPONSE_CONTENT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_RESPONSE_INDEX
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_RX_CRC7
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_DAT_RX_DONE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_ERROR_CRC16
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_ERROR_DAT_TIMES_OUT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/i_READ_REQUEST
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_sd_cmd_fsm/LIMIT_SD_TIMERS
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/i_START
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/i_FATAL_ERROR
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/i_RST
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/o_DONE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/o_G_CLK_SD_EN
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/o_HS_TO_INIT_CLK_DIVIDER_RST
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/my_clk_fsm/o_SD_CLK_SELECTED
|
||||
add wave -noupdate -group old -expand /sd_top_tb/DUT/w_OPCODE_Q
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_CMD
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_ACMD
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_Go_Idle_State
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R0_NONE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R0_NONE
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R1_NORMAL
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R2_CID_CSD
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R3_OCR
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R6_RCA
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/c_response_type_R7_CIC
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/w_instruction_control_bits
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/w_command_index
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/r_IC_OUT
|
||||
add wave -noupdate -group old /sd_top_tb/DUT/w_BLOCK_ADDR
|
||||
add wave -noupdate /sd_top_tb/DUT/w_TX_SOURCE_SELECT
|
||||
add wave -noupdate /sd_top_tb/DUT/w_tx_tail_Q
|
||||
add wave -noupdate /sd_top_tb/DUT/w_TX_PISO8_LOAD
|
||||
add wave -noupdate /sd_top_tb/DUT/w_TX_PISO8_EN
|
||||
add wave -noupdate /sd_top_tb/DUT/r_command_tail
|
||||
add wave -noupdate /sd_top_tb/DUT/r_TX_CRC7
|
||||
add wave -noupdate /sd_top_tb/DUT/w_TX_CRC7_PIPO_RST
|
||||
add wave -noupdate /sd_top_tb/DUT/w_TX_CRC7_PIPO_EN
|
||||
add wave -noupdate /sd_top_tb/DUT/w_command_head
|
||||
add wave -noupdate /sd_top_tb/DUT/my_sd_dat_fsm/i_DAT0_Q
|
||||
add wave -noupdate /sd_top_tb/sdcard/oeDat
|
||||
add wave -noupdate /sd_top_tb/sdcard/datOut
|
||||
add wave -noupdate /sd_top_tb/sdcard/dat
|
||||
add wave -noupdate /sd_top_tb/DUT/my_sd_cmd_fsm/w_resend_last_command
|
||||
add wave -noupdate /sd_top_tb/DUT/my_sd_cmd_fsm/i_ERROR_CRC16
|
||||
add wave -noupdate /sd_top_tb/DUT/r_DAT3_CRC16
|
||||
add wave -noupdate /sd_top_tb/DUT/r_DAT2_CRC16
|
||||
add wave -noupdate /sd_top_tb/DUT/r_DAT1_CRC16
|
||||
add wave -noupdate /sd_top_tb/DUT/r_DAT0_CRC16
|
||||
add wave -noupdate -radix decimal /sd_top_tb/DUT/my_sd_cmd_fsm/i_COUNTER_OUT
|
||||
add wave -noupdate /sd_top_tb/DUT/CLK
|
||||
add wave -noupdate /sd_top_tb/DUT/r_CLK_SD
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/i_COUNT_IN_MAX
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/i_EN
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/i_CLK
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/i_RST
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/g_COUNT_WIDTH
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/r_count_out
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/w_counter_overflowed
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/r_fd_Q
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/w_fd_D
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/w_load
|
||||
add wave -noupdate -expand -group {clock divider} /sd_top_tb/DUT/slow_clk_divider/o_CLK
|
||||
add wave -noupdate /sd_top_tb/sdcard/ByteAddr
|
||||
add wave -noupdate /sd_top_tb/sdcard/write_out_index
|
||||
add wave -noupdate /sd_top_tb/sdcard/inCmd
|
||||
add wave -noupdate /sd_top_tb/DUT/w_TX_SOURCE_SELECT
|
||||
add wave -noupdate /sd_top_tb/DUT/w_command_head
|
||||
add wave -noupdate /sd_top_tb/DUT/r_IC_OUT
|
||||
add wave -noupdate /sd_top_tb/DUT/w_BLOCK_ADDR
|
||||
add wave -noupdate /sd_top_tb/DUT/i_BLOCK_ADDR
|
||||
add wave -noupdate /sd_top_tb/DUT/regfile_cmd17_data_block/regs
|
||||
add wave -noupdate /sd_top_tb/DUT/regfile_cmd17_data_block/ra1
|
||||
TreeUpdate [SetDefaultTree]
|
||||
WaveRestoreCursors {{Cursor 1} {2028326 ns} 0} {{Cursor 2} {4831 ns} 0}
|
||||
quietly wave cursor active 1
|
||||
configure wave -namecolwidth 245
|
||||
configure wave -valuecolwidth 180
|
||||
configure wave -justifyvalue left
|
||||
configure wave -signalnamewidth 1
|
||||
configure wave -snapdistance 10
|
||||
configure wave -datasetprefix 0
|
||||
configure wave -rowmargin 4
|
||||
configure wave -childrowmargin 2
|
||||
configure wave -gridoffset 0
|
||||
configure wave -gridperiod 1
|
||||
configure wave -griddelta 40
|
||||
configure wave -timeline 0
|
||||
configure wave -timelineunits ns
|
||||
update
|
||||
WaveRestoreZoom {2013966 ns} {2038576 ns}
|
55
wally-pipelined/src/sdc/up_down_counter.sv
Normal file
55
wally-pipelined/src/sdc/up_down_counter.sv
Normal file
@ -0,0 +1,55 @@
|
||||
///////////////////////////////////////////
|
||||
// counter.sv
|
||||
//
|
||||
// Written: Ross Thompson
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: basic up counter
|
||||
//
|
||||
// A component of the Wally configurable RISC-V project.
|
||||
//
|
||||
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///////////////////////////////////////////
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
module up_down_counter #(parameter integer WIDTH=32)
|
||||
(
|
||||
input logic [WIDTH-1:0] CountIn,
|
||||
output logic [WIDTH-1:0] CountOut,
|
||||
input logic Load,
|
||||
input logic Enable,
|
||||
input logic UpDown,
|
||||
input logic clk,
|
||||
input logic reset);
|
||||
|
||||
logic [WIDTH-1:0] NextCount;
|
||||
logic [WIDTH-1:0] count_q;
|
||||
logic [WIDTH-1:0] CountP1;
|
||||
|
||||
flopenr #(WIDTH) reg1(.clk,
|
||||
.reset,
|
||||
.en(Enable | Load),
|
||||
.d(NextCount),
|
||||
.q(CountOut));
|
||||
|
||||
assign CountP1 = UpDown ? CountOut + 1'b1 : CountOut - 1'b1;
|
||||
|
||||
// mux between load and P1
|
||||
assign NextCount = Load ? CountIn : CountP1;
|
||||
|
||||
endmodule
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user